-
Notifications
You must be signed in to change notification settings - Fork 760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API spec declares that it produces application/json but swagger-client doesn't set Accept header. #1116
Comments
Can you provide an API definition that reproduces the issue? |
{
"swagger": "2.0",
"info": {
"title": "The API",
"version": "v0.1.0"
},
"schemes": [
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/organizations": {
"get": {
"summary": "List returns all the organizations where you are a member.",
"operationId": "List",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiOrgListResponse"
}
}
},
"tags": [
"Orgs"
]
},
"post": {
"summary": "Create creates a new organization",
"operationId": "Create",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiOrgCreateResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/apiOrgCreateRequest"
}
}
],
"tags": [
"Orgs"
]
}
},
"/organizations/{org_id}/is-admin": {
"get": {
"summary": "IsAdminUser checks whether the requesting user belongs to the admins or owners team within\nthe given organization.",
"operationId": "IsAdminUser",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiOrgIsAdminUserResponse"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "path",
"required": true,
"type": "string"
}
],
"tags": [
"Orgs"
]
}
},
"/password": {
"put": {
"summary": "ChangePassword changes the user password.",
"operationId": "ChangePassword",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiChangePasswordResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/apiChangePasswordRequest"
}
}
],
"tags": [
"Authz"
]
}
},
"/password-reset": {
"post": {
"summary": "SendPasswordResetLink sends a reset link to user's email address.",
"operationId": "SendPasswordResetLink",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiPasswordResetResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/apiPasswordResetRequest"
}
}
],
"tags": [
"Authz"
]
}
},
"/register": {
"post": {
"summary": "Register dynamically creates an OpenID Connect application.",
"operationId": "Register",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiRegisterApp"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/apiRegisterApp"
}
}
],
"tags": [
"Apps"
]
}
},
"/signup": {
"post": {
"summary": "SignUp creates an account.",
"operationId": "SignUp",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiSignUpResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/apiSignUpRequest"
}
}
],
"tags": [
"Authz"
]
}
},
"/teams": {
"get": {
"summary": "List returns all the teams where you are a member.",
"operationId": "List",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiTeamsListResponse"
}
}
},
"parameters": [
{
"name": "org_id",
"in": "query",
"required": false,
"type": "string"
}
],
"tags": [
"Teams"
]
}
},
"/userinfo": {
"get": {
"summary": "Info Returns user information.",
"operationId": "Info",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/apiInfoResponse"
}
}
},
"tags": [
"Accounts"
]
}
}
},
"definitions": {
"apiChangePasswordRequest": {
"type": "object",
"properties": {
"password1": {
"type": "string",
"title": "New password"
},
"password2": {
"type": "string",
"title": "New password confirmation"
}
}
},
"apiChangePasswordResponse": {
"type": "object"
},
"apiInfoResponse": {
"type": "object",
"properties": {
"sub": {
"type": "string"
},
"name": {
"type": "string"
},
"email": {
"type": "string"
},
"email_verified": {
"type": "boolean",
"format": "boolean"
},
"picture": {
"type": "string"
},
"last_signin": {
"type": "string",
"format": "date-time"
}
},
"title": "UserinfoResponse as defined in http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse"
},
"apiIssueTokenResponse": {
"type": "object",
"properties": {
"access_token": {
"type": "string",
"title": "AccessToken is the signed access token in JWT format"
},
"token_type": {
"type": "string",
"description": "TokenType is the access token type, always Bearer."
},
"refresh_token": {
"type": "string",
"description": "RefreshToken is the new refresh token."
},
"expires_in": {
"type": "string",
"format": "int64",
"description": "ExpiresIn is the time in seconds after which the access token is no longer valid."
},
"id_token": {
"type": "string",
"description": "IdToken is the signed ID token in JWT format."
},
"state": {
"type": "string",
"description": "State is a value provided by the client, used to prevent CSRF attacks."
}
},
"description": "IssueTokenResponse is the message sent back to the client application upon requesting tokens with any of the grant types supported."
},
"apiOrgCreateRequest": {
"type": "object"
},
"apiOrgCreateResponse": {
"type": "object"
},
"apiOrgIsAdminUserResponse": {
"type": "object",
"properties": {
"teams": {
"type": "object",
"additionalProperties": {
"type": "boolean",
"format": "boolean"
}
}
},
"description": "OrgIsAdminUserResponse contains the \"admin\" teams the user belongs to in the queried organization."
},
"apiOrgListResponse": {
"type": "object",
"description": "OrgListResponse ..."
},
"apiPasswordResetRequest": {
"type": "object",
"properties": {
"email": {
"type": "string"
}
}
},
"apiPasswordResetResponse": {
"type": "object"
},
"apiRegisterApp": {
"type": "object",
"properties": {
"redirect_uris": {
"type": "array",
"items": {
"type": "string"
},
"description": "RedirectUris is the list of Redirection URI values used by the Client. REQUIRED."
},
"response_types": {
"type": "array",
"items": {
"type": "string"
},
"description": "ResponseTypes is the list of the OAuth 2.0 response_type values that the Client is declaring that it will restrict itself to using."
},
"grant_types": {
"type": "array",
"items": {
"type": "string"
},
"description": "GrantTypes is the list of the OAuth 2.0 Grant Types that the Client is declaring that it will restrict itself to using."
},
"application_type": {
"type": "string",
"description": "ApplicationType is the kind of the application. The default, if omitted, is web. The defined values are native or web.\nWeb Clients using the OAuth Implicit Grant Type MUST only register URLs using the https scheme as redirect_uris; they MUST NOT use\nlocalhost as the hostname. Native Clients MUST only register redirect_uris using custom URI schemes or URLs using the http: scheme\nwith localhost as the hostname."
},
"contacts": {
"type": "array",
"items": {
"type": "string"
},
"description": "Contacts is the list of e-mail addresses of people responsible for this Client."
},
"client_name": {
"type": "string",
"description": "ClientName is the name of the Client to be presented to the End-User. REQUIRED."
},
"logo_uri": {
"type": "string",
"description": "LogoUri is the URL that references a logo for the Client application."
},
"client_uri": {
"type": "string",
"description": "ClientUri is the URL of the home page of the Client. The value of this field MUST point to a valid Web page."
},
"policy_uri": {
"type": "string",
"description": "PolicyUri is the URL that the Relying Party Client provides to the End-User to read about the how the profile data will be used."
},
"tos_uri": {
"type": "string",
"description": "TosUri is the URL that the Relying Party Client provides to the End-User to read about the Relying Party's terms of service."
},
"jwks_uri": {
"type": "string",
"description": "JwksUri is the URL for the Client's JSON Web Key Set [JWK] document. If the Client signs requests to the Server, it contains the\nsigning key(s) the Server uses to validate signatures from the Client."
},
"jwks": {
"type": "string",
"description": "Jwks is the Client's JSON Web Key Set [JWK] document, passed by value. This parameter is intended only to be used by Clients that, for\nsome reason, are unable to use the jwks_uri parameter, for instance, by native applications that might not have a location to host the contents of the JWK Set."
},
"sector_identifier_uri": {
"type": "string",
"description": "SectorIdentifierUri is the URL using the https scheme to be used in calculating Pseudonymous Identifiers by the OP."
},
"subject_type": {
"type": "string",
"description": "SubjectType is the value requested for responses to this Client. Valid types for Hooklift identity server include only \"public\"."
},
"id_token_signed_response_alg": {
"type": "string",
"title": "IdTokenSignedResponseAlg is the JWS alg algorithm [JWA] REQUIRED for signing the ID Token issued to this Client. The value none MUST NOT be used as the\nID Token alg value unless the Client uses only Response Types that return no ID Token from the Authorization Endpoint (such as when only using the Authorization Code Flow)"
},
"id_token_encrypted_response_alg": {
"type": "string",
"description": "IdTokenEncryptedResponseAlg is the JWE alg algorithm [JWA] REQUIRED for encrypting the ID Token issued to this Client. If this is requested, the response will be signed\nthen encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that no encryption is performed."
},
"id_token_encrypted_response_enc": {
"type": "string",
"description": "IdTokenEncryptedResponseEnc is the JWE enc algorithm [JWA] REQUIRED for encrypting the ID Token issued to this Client. If id_token_encrypted_response_alg\nis specified, the default for this value is A128CBC-HS256. When id_token_encrypted_response_enc is included, id_token_encrypted_response_alg MUST also be provided."
},
"userinfo_signed_response_alg": {
"type": "string",
"description": "UserinfoSignedResponseAlg is the JWS alg algorithm [JWA] REQUIRED for signing UserInfo Responses. If this is specified, the response will be JWT [JWT] serialized, and signed\nusing JWS. The default, if omitted, is for the UserInfo Response to return the Claims as a UTF-8 encoded JSON object using the application/json content-type."
},
"userinfo_encrypted_response_alg": {
"type": "string",
"description": "UserinfoEncryptedResponseAlg is the JWE [JWE] alg algorithm [JWA] REQUIRED for encrypting UserInfo Responses. If both signing and encryption are requested, the response\nwill be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. The default, if omitted, is that no encryption is performed."
},
"userinfo_encrypted_response_enc": {
"type": "string",
"description": "UserinfoEncryptedResponseEnc is the JWE enc algorithm [JWA] REQUIRED for encrypting UserInfo Responses. If userinfo_encrypted_response_alg is specified, the\ndefault for this value is A128CBC-HS256. When userinfo_encrypted_response_enc is included, userinfo_encrypted_response_alg MUST also be provided."
},
"request_object_signing_alg": {
"type": "string",
"description": "RequestObjectSigningAlg is the JWS [JWS] alg algorithm [JWA] that MUST be used for signing Request Objects sent to the OP. All Request Objects from this Client will be rejected,\nif not signed with this algorithm. Request Objects are described in Section 6.1 of OpenID Connect Core 1.0 [OpenID.Core]. This algorithm MUST be used both when the Request Object\nis passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter). The value none MAY be used. The default, if omitted,\nis that any algorithm supported by the OP and the RP MAY be used."
},
"request_object_encryption_alg": {
"type": "string",
"description": "RequestObjectEncryptionAlg is the JWE [JWE] alg algorithm [JWA] the RP is declaring that it may use for encrypting Request Objects sent to the OP. This parameter SHOULD be\nincluded when symmetric encryption will be used, since this signals to the Hooklift Identity Provider that a client_secret value needs to be returned from which the symmetric\nkey will be derived, that might not otherwise be returned. The RP MAY still use other supported encryption algorithms or send unencrypted Request Objects, even when this\nparameter is present. If both signing and encryption are requested, the Request Object will be signed then encrypted, with the result being a Nested JWT, as defined in [JWT].\nThe default, if omitted, is that the RP is not declaring whether it might encrypt any Request Objects."
},
"request_object_encryption_enc": {
"type": "string",
"description": "RequestObjectEncryptionEnc is the JWE enc algorithm [JWA] the RP is declaring that it may use for encrypting Request Objects sent to the OP. If request_object_encryption_alg\nis specified, the default for this value is A128CBC-HS256. When request_object_encryption_enc is included, request_object_encryption_alg MUST also be provided."
},
"token_endpoint_auth_method": {
"type": "string",
"description": "TokenEndpointAuthMethod is the Requested Client Authentication method for the Token Endpoint. The only option supported by Hooklift Identity is client_secret_basic.\nIf omitted, the default is client_secret_basic -- the HTTP Basic Authentication Scheme specified in Section 2.3.1 of OAuth 2.0 [RFC6749]."
},
"token_endpoint_auth_signing_alg": {
"type": "string",
"description": "TokenEndpointAuthSigningAlg is the JWS [JWS] alg algorithm [JWA] that MUST be used for signing the JWT [JWT] used to authenticate the Client at the Token Endpoint for the\nprivate_key_jwt and client_secret_jwt authentication methods. All Token Requests using these authentication methods from this Client will be rejected, if the JWT is not\nsigned with this algorithm. The value none MUST NOT be used. The default, if omitted, is that any algorithm supported by the OP and the RP MAY be used."
},
"default_max_age": {
"type": "integer",
"format": "int32",
"description": "DefaultMaxAge is the Default Maximum Authentication Age. Specifies that the End-User MUST be actively authenticated if the End-User was authenticated longer ago than the\nspecified number of seconds. If omitted, no default Maximum Authentication Age is specified."
},
"require_auth_time": {
"type": "boolean",
"format": "boolean",
"description": "RequireAuthTime is a boolean value specifying whether the auth_time Claim in the ID Token is REQUIRED. It is REQUIRED when the value is true. (If this is false, the\nauth_time Claim can still be dynamically requested as an individual Claim for the ID Token using the claims request parameter described in Section 5.5.1 of\nOpenID Connect Core 1.0 [OpenID.Core].) If omitted, the default value is false."
},
"default_acr_values": {
"type": "array",
"items": {
"type": "string"
},
"description": "DefaultAcrValues is the Default requested Authentication Context Class Reference values. Array of strings that specifies the default acr values that the OP is being\nrequested to use for processing requests from this Client, with the values appearing in order of preference. The Authentication Context Class satisfied by the\nauthentication performed is returned as the acr Claim Value in the issued ID Token. The acr Claim is requested as a Voluntary Claim by this parameter.\nThe acr_values_supported discovery element contains a list of the supported acr values supported by this server. Values specified in the acr_values\nrequest parameter or an individual acr Claim request override these default values."
},
"initiate_login_uri": {
"type": "string",
"description": "InitiateLoginUri is the URI using the https scheme that a third party can use to initiate a login by the RP, as specified in Section 4 of OpenID Connect Core 1.0 [OpenID.Core].\nThe URI MUST accept requests via both GET and POST. The Client MUST understand the login_hint and iss parameters and SHOULD support the target_link_uri parameter."
},
"request_uris": {
"type": "array",
"items": {
"type": "string"
},
"description": "RequestUris are the list of request_uri values that are pre-registered by the RP for use by Hooklift Identity."
},
"client_id": {
"type": "string",
"description": "ClientId is the unique identifier generated for the registered application."
},
"client_secret": {
"type": "string",
"description": "ClientSecret is the password assigned to the registered application."
},
"registration_access_token": {
"type": "string",
"description": "RegistrationAccessToken is the Access Token that can be used at the Client Configuration Endpoint to perform subsequent operations upon the Client registration."
},
"registration_client_uri": {
"type": "string",
"description": "RegistrationClientUri is the location of the Client Configuration Endpoint where the Registration Access Token can be used to perform subsequent operations upon the resulting Client registration."
},
"client_id_issued_at": {
"type": "string",
"format": "date-time",
"description": "ClientIdIssuedAt is the time at which the Client Identifier was issued."
},
"client_secret_expires_at": {
"type": "integer",
"format": "int32",
"description": "ClientSecretExpiresAt is the time at which the client secret will expire or 0 if it will not expire. Its value is the number of seconds since 1970-01-01T0:0:0Z in UTC."
},
"error": {
"type": "string",
"description": "Error is the error code returned by Hooklift Identity if there was any error registering the client application."
},
"error_description": {
"type": "string",
"description": "ErrorDescription is a detailed description explaining why the transaction failed."
}
},
"description": "RegisterApp represents the request and response required in order to register OpenIDC client applications."
},
"apiSignInResponse": {
"type": "object",
"properties": {
"access_token": {
"type": "string",
"description": "AccessToken contains a JWT token, that is, cryptographically signed Base64-encoded JSON object token."
},
"refresh_token": {
"type": "string",
"description": "RefreshToken contains a token with no expiration, that allows the client application to get new access tokens with the same granted scope."
},
"token_type": {
"type": "string",
"description": "TokenType is set to \"Bearer\" as per the OAuth2 spec."
},
"expires_in": {
"type": "string",
"description": "ExpiresIn is the time in seconds during which the access token will be valid."
},
"id_token": {
"type": "string",
"description": "IdToken is a JWT token, that is, cryptographically signed Base64-encoded JSON object token containing user information such as email and name."
},
"state": {
"type": "string",
"description": "State should be the same random value provided in the original request. It should be verified in order to minimize the risk for CSRF attacks."
},
"code": {
"type": "string",
"description": "Code is the authorization grant code that could be use to revoke all tokens generated using this grant code."
}
},
"description": "SignInResponse contains the generated OAuth2 and OpenID Connect tokens, upon successful sign-in."
},
"apiSignOutResponse": {
"type": "object"
},
"apiSignUpRequest": {
"type": "object",
"properties": {
"username": {
"type": "string",
"title": "Username"
},
"email": {
"type": "string",
"title": "Email address"
}
}
},
"apiSignUpResponse": {
"type": "object"
},
"apiTeamsListResponse": {
"type": "object"
},
"apiToken": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "ID is the token unique identifier."
},
"issuer": {
"type": "string",
"description": "Issuer is the Open ID Connect provider who issued the token."
},
"subject": {
"type": "string",
"description": "Subject is the unique identifier for the user within the issuer."
},
"audience": {
"type": "array",
"items": {
"type": "string"
},
"description": "Audience is a list of client unique identifiers for which the token is intended for."
},
"expiry": {
"type": "string",
"format": "int64",
"description": "Expiry is the expiration time after which the token must not be accepted for processing."
},
"not_before": {
"type": "string",
"format": "int64",
"description": "NotBefore is the time after which the token can start to be used."
},
"issued_at": {
"type": "string",
"format": "int64",
"description": "IssuedAt is the time when the token was created."
},
"scopes": {
"type": "object",
"additionalProperties": {
"type": "boolean",
"format": "boolean"
},
"description": "Scopes is a list of permissions allowed for the token by the resource owner."
}
},
"description": "Token represents a decoded and verified JWT access token. It is returned by accounts.VerifyToken service\nwhich is only used by Hooklift properties."
},
"apiVerifyTokenResponse": {
"type": "object",
"properties": {
"token": {
"$ref": "#/definitions/apiToken"
}
},
"description": "VerifyTokenResponse returns a verified access token decoded."
}
},
"securityDefinitions": {
"bearer": {
"description": "Bearer authorization token",
"type": "oauth2",
"name": "Authorization",
"in": "header"
}
},
"security": [
{
"bearer": []
}
]
} |
FWIW, the only instance I found swagger-js setting the Accept header was here: Line 113 in c68c9a4
|
FWIW, I worked around this by wrapping |
@c4milo, are you using buildRequest/execute, or the tags interface? |
@shockey, I'm not sure, I believe I'm using the normal constructor. This is what my Nuxt.js plugin looks like right now: import Vue from 'vue';
import Swagger from 'swagger-client';
import APISpec from 'assets/identity.swagger.json';
const APIClient = {
install (Vue, options) {
let swaggerExecute = Swagger.execute;
// We wrap this function as a temporary workaround while SwaggerJS
// fixes an issue where the accept header wouldn't be set despite the spec
// declaring producing content with a specific mime type.
// More info: https://github.com/swagger-api/swagger-js/issues/1116
Swagger.execute = function execute ({
http: userHttp,
fetch, // This is legacy
spec,
operationId,
pathName,
method,
parameters,
securities,
...extras
}) {
extras.responseContentType = 'application/json';
return swaggerExecute.call(this, {
http: userHttp,
fetch, // This is legacy
spec,
operationId,
pathName,
method,
parameters,
securities,
...extras
});
};
Swagger({
spec: APISpec,
authorizations: {
bearer: {
token: {
access_token: ''
}
}
}
}).then(client => {
Vue.prototype.$client = client;
Vue.prototype.$api = client.apis;
}, error => {
console.error('failed to load api spec: %o', error);
});
}
};
Vue.use(APIClient); |
@c4milo, thanks for sharing how you're using the library. Which operation should I try to execute in order to reproduce this? |
@shockey any operation from your API. swagger-client will not set the accept header to |
@shockey, I'm thinking more about this. I think this could be solved easily by just allowing users to specify their accept header in the constructor, leaving the current default if none is provided: |
Hi @c4milo, so sorry this thread got lost!
This isn't possible in the constructor, but since you're using the tags interface, you can pass client.apis.Authz.ChangePassword({
body: {a: 1234}
}, {
responseContentType: 'application/json'
}) Further, yes this is a bug. I'm going to label it correctly so it stays on our radar! |
What is the state of this? the proposed adding of responseContentType works but it does not make the code look nicer. |
Yea this issue is causing me major headaches. The swagger-js client is the one used also in the swagger-ui correct? I am wondering why does it set the correct Accept header there, and not here. |
The right way to handle multiple content types would be to pass them all as list, like:
|
… in the API This fix uses the content-type defined in the operation and sets the accept header, to contain all of these content-types. If the option `responseContentType` is provided, only this value will be set as accept header. resolves swagger-api#1116
… in the API This fix uses the content-type defined in the operation and sets the accept header, to contain all of these content-types. If the option `responseContentType` is provided, only this value will be set as accept header. resolves swagger-api#1116
…correct-accept-header' into bugfix/swagger-apigh-1116-use-correct-accept-header
… in the API This fix uses the content-type defined in the operation and sets the accept header, to contain all of these content-types. If the option `responseContentType` is provided, only this value will be set as accept header. resolves swagger-api#1116
Set accept header according to the the produces content-types defined in the API. This fix uses the content-type defined in the operation and sets the accept header, to contain all of these content-types. If the option responseContentType is provided, only this value will be set as accept header. Closes #1116
No description provided.
The text was updated successfully, but these errors were encountered: