3
votes

While hitting an API from Postman I am getting this error.

API details:

URL:

https://account-perf.myglobal.com/v1/users/00uk0khprrME7gZOU0h7/credentials/change_password

Header:

Content-Type:application/json
Authorization:Bearer n7mbkw74jsubd7rauhptdnre

Type:

POST

Body:

{"password":"Baddy125@","token":"eyJhbGci...."}

Edit 1:

Web-service call to generate token-

URL-

https://api-perf.myglobal.com/rest/oauth2/v1/token

Type-

POST

Body-

client_id:abcd
client_secret:xyz
grant_type:client_credentials

4
n7mbkw74jsubd7rauhptdnre how did you generate this value? - Chetan

4 Answers

3
votes

I had this whenever any unhandled endpoint method or resource was called. My setup is an API Gateway with defined resources (e.g. /myendpoint) and defined methods for those endpoints (e.g. GET).

To fix it, I created a Node.js Lambda function that just returned a 404. Then I added any ANY method at the root of the endpoints / and pointed it as a Lambda proxy function to the ANY methods.

Then I added a proxy resource, e.g. /{proxy} -- there's a checkbox you can click when creating a resource to tell it to proxy. An ANY method on that resource pointing to the same Lambda function, deploy the API, and I'm done.

Now instead of the auth bearer token error, I get a proper HTTP 404 error.

2
votes

@Matt H - That's pretty good idea this gave me an inspiration of another one.

Assuming all of the other paths within the API are explicitly specified, I created a default path /{proxy+} which would return a http 404, message resource not found. Instead of using lambda, I was able to create a mock response, so there isn't even any cost incurred for getting Lambda to return the response.

I created my APIs via Open API spec. This is how my YAML for the implementation would like

  /{proxy+}:
    x-amazon-apigateway-any-method:
      responses:
        404:
          description: "404 response"
          content: {}
      x-amazon-apigateway-integration:
        responses:
          404:
            statusCode: "404"
            responseTemplates:
              application/json: "{\"message\":\"resource not available\"}"
        requestTemplates:
          application/json: "{\"statusCode\": 404}"
        passthroughBehavior: "when_no_templates"
        type: "mock"

Serverless also has the ability to specify inline mock response. Below can be a sample:

functions:
  default:
    handler: handler.default
    events:
      - http:
          path: hello
          cors: true
          method: get
          integration: mock
          request:
            template:
              application/json: '{"statusCode": 404}'
          response:
            template: $input.path('$')
            statusCodes:
              404:
                pattern: '' #default method
                template:
                  application/json: '{"statusCode": 404, "message":"resource not found"}'

serverless doc: https://www.serverless.com/framework/docs/providers/aws/events/apigateway/#custom-response-templates

1
votes

Analyze and validate the request path, in case the request is incorrect this error is thrown at API Gateway. I stepped on the same error, when corrected the request parameters it worked well.

Let me know.

0
votes

I managed to do it by proxying the ANY /{proxy+} route to a lambda which will always respond with an HTTP 404

Since all other routes are precisely configured, this ANY /{proxy+} route acts as the default one and will catch any unmatched request

Here is how I did it with CloudFormation :

Parameters:
    RestAPI:
        Type: String
    RestApiRootResourceId:
        Type: String
    LambdaName:
        Type: String
    Path:
        Type: String

RootResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref RestAPI
      ParentId: !Ref RestApiRootResourceId
      PathPart: !Ref Path
ProxyResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref RestAPI
      ParentId: !Ref RestApiRootResourceId
      PathPart: "{proxy+}"
AnyMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
    RestApiId: !Ref RestAPI
    ResourceId: !Ref ProxyResource
    HttpMethod: ANY
    Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        PassthroughBehavior: WHEN_NO_MATCH
        Uri:
          Fn::Join:
            - ":"
            - - !Sub "arn:aws:apigateway:${AWS::Region}:lambda"
              - !Sub "path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function"
              - !Sub "${LambdaName}/invocations"
ApiGatewayInvokeLambdaPermissionAny:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::Join:
          - ":"
          - - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function"
            - !Ref LambdaName
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
          - ":"
          - - !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}"
            - !Sub "${RestAPI}/*/ANY/*"

Paramters :

  • RestAPI is your API ID
  • RestApiRootResourceId is the ID of the root resource (!GetAtt "RestApi.RootResourceId")
  • LambdaName is the name of your proxy lambda
  • Path is something I have bewteen the stage and the root (for mty specific usage)