Git Product home page Git Product logo

claudia-api-builder's People

Contributors

aaronjameslang avatar andorbal avatar bryant1410 avatar gojko avatar jcn avatar mikefrey avatar phips28 avatar pmarkert avatar stojanovic avatar vinagrito avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

claudia-api-builder's Issues

CORS not restricting domains


Expected behaviour:

Run the example-projects/web-api-custom-cors and test the following request:

curl 'https://xxxxxxx.execute-api.eu-west-1.amazonaws.com/latest/echo' -H 'Origin: https://www.foo.bar' -vvvv

Should not return following header since Origin is not claudiajs.com:

Access-Control-Allow-Origin: *

What actually happens:

Returns header:

Access-Control-Allow-Origin: *

Throwing classes derived from ApiBuilder.ApiResponse is not working correctly

  • Expected behaviour: If an error is instanceof ApiBuilder.ApiResponse, it should work the same as if it is exactly that class.

  • What actually happens: If an error class is inheriting from ApiBuilder.ApiResponse, it no longer functions like a response object but instead results in an errorMessage with a JSON representation of the error.

class NotFoundError extends ApiBuilder.ApiResponse {
  constructor (message = 'Not found') {
    super(JSON.stringify({ error: message }), { 'Content-Type': 'application/json' }, 404)
  }
}

// This doesn't work
throw new NotFoundError()

// This works
throw new ApiBuilder.ApiResponse(JSON.stringify({ error: 'Not found' }), { 'Content-Type': 'application/json' }, 404)

// This is true, so why does it not work?
console.log(new NotFoundError() instanceof ApiBuilder.ApiResponse)

Multiple Lambdas per API Gateway

Is there a way that two lambda functions monitored Claudia can point to the same api. For instance if I wanted to create two crud modules controlled in separate claudia projects but using the same api is there a way of specifying a merge so claudia updates will not clobber the existing api?

CORS with Cognito Authorizer

Can anyone show me a snippet of code that demonstrates an endpoint that responds to GET requests, requires an Authorization header, uses Cognito as an authorizer, and allows CORS requests from exactly two domain names?

The documentation on these things seems to be out of date, possibly. When I leave Cognito authentication out, CORS works just fine for either all domains or exactly one. When I add a Cognito Authorizer, CORS headers are present on OPTIONS responses, but not any of the other HTTP verbs.

No combination of static endpoint configuration object, ApiResponse object--one or both together--seems to work as expected when both CORS and authentication are required.

Documentation: Pont out where claudia looks for credentials

While going over the guide there is a link pointing to the configuration of the AWS node SDK specifically about how to set up credentials.
On the linked page there are several methods to add credentials to the node sdk. But it is not exactly clear which one Claudia uses for connecting to the api.
Can this be clarified with a sentence: "Claudia uses ~/.sdk/config file" or "Claudia uses a json file in your project"?

Thanks!

Use root path as resource

When I set:

api.get('/', myThing)

Then run claudia update, I get an error:

{
     message: 'Resource\'s path part must be specified',
     code: 'BadRequestException',
     time: Mon Feb 22 2016 20:47:08 GMT-0600 (CST),
     requestId: 'bb2ad343-d9d7-11e5-bc97-275099d33c06',
     statusCode: 400,
     retryable: false,
     retryDelay: 71.45924023352563
 }

Is this deliberate in Claudia? It appears to be possible in the AWS console.

Add 'Access-Control-Allow-Origin' header to Authorizer's error responses

When using Cognito Authorizer, I'm hitting an endpoint being Unauthorized, browser throws the following error:

"No 'Access-Control-Allow-Origin' header is present on the requested resource"

This can be solved in API Gateway Console by setting a 'Access-Control-Allow-Origin' header in 'Gateway responses' > 'Unauthorized' > 'Response header'

Would be great if this header can be set by ClaudiaJS automatically (probably it's a good idea to set it on other responses as well).

Dynamic routing parameters

Hi guys - love the project. Dead simple to get started with.

I'd love a simple routing enhancement so that you can catch parameters in the URL.

var ApiBuilder = require("claudia-api-builder");
var api = new ApiBuilder();

api.get("/get/{id}", function (request) {
   return request.id; 
});

So if I access this with /get/123 I'll get 123 back

Can't make API return a function's callback

I'm trying to use the claudia-api-builder along side woocommerce-api. No matter how I try to do organize my code, the Lambda endpoint returns me the first call: WooCommerce.get() and not it's callback, which contains the response data (formatedData).

Here's the code:

api.get('/products', (req, res) => {
  const WooCommerce = new WooCommerceAPI({
    url: req.env.configUrl,
    consumerKey: req.env.configConsumerKey,
    consumerSecret: req.env.configConsumerSecret,
  });

  const promise = Promise.resolve(
    WooCommerce.get('products', (err, data, response) => {
      if(data.statusCode === 200) {
        const formatedData = JSON.parse(response)
        return formatedData;
      } else {
        return response;
      }
    })
  );

  return promise.then((res) => {
    return res
  });
});

How should I organize the functions in order to have the API return the callback of WooCommerce.get()?

Support for ApiResponse customization in intercept()

I was surprised to find that api.intercept() did not handle custom errors/responses, but instead always returned 500 Internal Server Error. I had expected that if I threw an instance of ApiResponse, that it would use the status, body, and headers, but instead the handler passes the value as-is to the error parameter on the lambda callback.

Type defintions for IDEs

Please use GitHub issues only to report bugs. To ask a general question or request assistance/support, please use the Claudia.js Gitter Chat instead.

To report a bug or a problem, please fill in the sections below. The more you provide, the better we'll be able to help.

I am currently using WebStorm, and when I try to use the API Builder, I see that the IDE cannot recognize the functions.


  • Expected behavior:
    No errors in IDE

  • What actually happens:
    Undefined warnings appear in WebStorm

  • Link to a minimal, executable project that demonstrates the problem:

  • Steps to install the project:

  • Steps to reproduce the problem:

One API Gateway for different lambda.

Hello guys, how can I deploy different services to one API gateway endpoint? I just want to have one API Gateway endpoint which provides access to all my services in lambda. It is possible?

Premature Exit while using Async.js with no results

Please use GitHub issues only to report bugs. To ask a general question or request assistance/support, please use the Claudia.js Gitter Chat instead.

To report a bug or a problem, please fill in the sections below. The more you provide, the better we'll be able to help.


  • Expected behaviour:
    Results of a mongoose .find call

  • What actually happens:
    Nothing. Cloudwatch logs show:
    START RequestId: dc0bc7a1-262e-11e7-b0af-8f68d1af4f11 Version: $LATEST END RequestId: dc0bc7a1-262e-11e7-b0af-8f68d1af4f11 REPORT RequestId: dc0bc7a1-262e-11e7-b0af-8f68d1af4f11 Duration: 136.11 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 44 MB

  • Link to a minimal, executable project that demonstrates the problem:
    My only "route"
    https://repl.it/HTEz

I am running lambda with node 6.1

JSON parse throws error

When calling claudia API using HTTP POST and invalid JSON like:
{test:true}

One will get following error:
{
"message": "Internal server error"
}

=>

SyntaxError: Unexpected token t
at Object.parse (native)
at convertApiGWProxyRequest (/var/task/node_modules/claudia-api-builder/src/convert-api-gw-proxy-request.js:80:22)
at ApiBuilder.getRequest (/var/task/node_modules/claudia-api-builder/src/api-builder.js:233:12)
at ApiBuilder.self.proxyRouter (/var/task/node_modules/claudia-api-builder/src/api-builder.js:322:19)

Maybe you can catch the error from JSON.parse and use empty JSON in turn?

A sibling ({uuid}) of this resource already has a variable path part -- only one is allowed

Please use GitHub issues only to report bugs. To ask a general question or request assistance/support, please use the Claudia.js Gitter Chat instead.

To report a bug or a problem, please fill in the sections below. The more you provide, the better we'll be able to help.


  • Expected behaviour:
    It should deploy without any problem...
  • What actually happens:
  • A sibling ({uuid}) of this resource already has a variable path part -- only one is allowed
  • Link to a minimal, executable project that demonstrates the problem:
    I don't have a sample, but I hope the explanation above is enough.

  • Steps to install the project:

  • Steps to reproduce the problem:

When run npm run cl:deploy, it return the error below.

A sibling ({uuid}) of this resource already has a variable path part -- only one is allowed

The router below has a pathParam id

api.delete("/admin/{hash}/users/{id}", async request => {
  }, responseIndentifier("delete"));

However when I remove the pathParam from the above route, I add a pathParam to the route below. When I try to deploy it, it works!!!, WHY?

api.delete('/admin/{hash}/users/{user_uuid}/post/{uuid}', async request => {
  }, responseIndentifier('delete'));

304 Not modified responds like a redirect

I have a large response that changes infrequently that is a good use case for a status 304 to the browser. When I use that currently the json body that I have built is assigned to the Location response header.

In the handler I send back an ETag and test the If-None-Matchto see if a 304 is fitting.

An example of how simple the tests + fix can be https://github.com/chamaeleonidae/claudia-api-builder/commit/8d1222fefd67c6d7730a5707a42dd4d711630455

If this is useful I'll add a PR to support 304's

Support route regex

It seems now only supports fixed route, like "hello", how to support "hello*"?

The real problem is I want to support rest service like '/project/:id?' and '/media/:id?', or more types in future. I don't want to add same code in the router. Also in AWS API Gateway, it's not necessary to create multiple resources, I just have two, "/{model}" and "/{model}/{id}".

If API Gateway supports regex, I hope just one resource like "/{model}/{id}?".

Handle files upload

Provide a way, along with request objects to deal with file uploads (from api to a bucket).

AWSOME job you did here by the way! ;)

Handling dynamic path variables when running locally

Would be nice if there was a standard way to have dynamic paths working locally, or some documentation about it not working in certain environments.

The functionality I'm talking about is here, with the lines starting right around here making this functionality impossible.

Default CORs settings (allow-origin: * & allow-credentials: true) Breaks Ajax

  • Expected behaviour:
    By default OPTION show not have access-control-allow-credentials: "true" set by default.

  • What actually happens:
    The default behavior of an endpoint in claudia rest has wildcard and allow-credentials true.

HTTP/2.0 200 OK
content-type: application/json
content-length: 0
date: Wed, 04 Mar 2020 18:11:26 GMT
x-amzn-requestid: 30853b72-2dc9-4734-9bcf-034dcfc63a6d
access-control-allow-origin: *         <<<< ISSUE
access-control-allow-headers: Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token
x-amz-apigw-id: I4JUTGEUoAMF8YA=
access-control-allow-methods: OPTIONS,GET,POST
access-control-allow-credentials: true       <<<< ISSUE
x-cache: Miss from cloudfront
.....

This combination of current default options:

access-control-allow-credentials: "true"
and
access-control-allow-origin: *  

Throws a security issue in ALL browsers during a cross domain AJAX request. To obey the security model, if access-control-allow-credentials: "true" then the access control must be a full origin access-control-allow-origin: https://test.com:5050

  • Steps to reproduce the problem:

Start a new project with one end point, load it via ajax from a different domain.

Wrong document in cors.md

/claudiajs.com$/.test(request.headers.Origin)

Actually it should check:

/claudiajs.com$/.test(request.normalizedHeaders.origin)

which is documented correctly here: https://github.com/claudiajs/example-projects/blob/master/web-api-custom-cors/web.js

Unable to use ApiResponse to return readable errors when serving binary content

  • Expected behaviour:

Say for example, you have a lambda that serves dynamic images, but in the case that some part of the process fails you want to be able to respond with a context-specific status code (which is something I'm looking at doing). It seems like you should be able to use ApiResponse objects to dynamically determine whether you return something like
new api.ApiResponse(buffer, { 'Content-Type': 'image/png' }, 200)
on success or
new api.ApiResponse(error.toString(), {'Content-Type': 'text/plain' }, error.status)
on an error.

  • What actually happens:

You don't seem to be able to set the { success: { contentHandling: 'CONVERT_TO_BINARY' } } flag inside an ApiResponse object which leads to all content being converted to binary, including the errors. The HTTP status is fine, but the error message is unreadable nonsense. If you leave that off the declaration of the endpoint, images obviously don't get converted to binary, although errors then are fine. It looks like ApiResponses that handle error status codes aren't treated like actual errors, and still trigger flags in the "success" object. Looking at the source code in src/api-builder seems to confirm this:

} else if (isApiResponse(modifiedRequest)) {
return context.done(null, packResult(modifiedRequest, getRequestRoutingInfo(request), {}, 'success'));

packResult being where

if (configuration && configuration.contentHandling === 'CONVERT_TO_BINARY' && resultType === 'success') {
result.isBase64Encoded = true;
}

happens.

At any rate, it seems like there should be some sort of way to either set contentHandling: 'CONVERT_TO_BINARY' in a specific ApiResponse object to to not treat ApiResponses like successes universally.

  • Link to a minimal, executable project that demonstrates the problem:

Something along the lines of this should do the trick:

import APIBuilder from 'claudia-api-builder'
import fs from 'fs'
import path from 'path'

const API = new APIBuilder()

API.get('/{x}', (req) => {
    const param = req.pathParams.x

    if (isNaN(x)) return new API.ApiResponse('Error: x is meant to be a number.', { 'Content-Type': 'text/plain' }, 400)

    const img = fs.readFileSync(path.join(__dirname, './img.png'))
    return new API.ApiResponse(img, { 'Content-Type': 'image/png' }, 200)

}, { success: { contentHandling: 'CONVERT_TO_BINARY' }})
  • Steps to install the project:
    Run yarn install and deploy the project to AWS.

  • Steps to reproduce the problem:

Access the endpoint using a number and the image should be served fine, but doing so with a string should get you a 400 status and an unreadable buffer.
Caveat: AWS API Gateway has issues serving images if you navigate to the endpoint but you'll be able to curl it with -H "Accept: image/png"

Possible to specify response as combination of status code and body

From reading the docs, it looks like all error responses get the same status code and content type. Is it possible specify these in the handler? For example:

api.get('/', function () {
    if (isBadRequest) return { "message": "Bad request" } // 400 
    if (isForbidden) return { "message": "Forbidden" } // 403 
    return { "message": "Success" } // 200
})

Authorization with Cognito User Pools and Axios client-side

I'd like to add cognito user pool authorization to my claudia api, but I keep on getting cors errors. My current error is "CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."

My back-end uses:

var ApiBuilder = require('claudia-api-builder');
app = new ApiBuilder();
app.registerAuthorizer('MyCognitoAuth', {
    providerARNs: [<my user pool Arn>]
});
app.corsHeaders('Content-Type,Authorization,foo,bar');

I'm using Vue (axios) for my front-end, with calls that look like

const api =  axios.create({
  baseURL: `https://8d0g0s8dmc.execute-api.us-east-2.amazonaws.com/latest`,
  headers: {
    "Access-Control-Allow-Credentials" : true,
    "Access-Control-Allow-Origin": "*",
    'Authorization': localStorage.mtopToken
  }
});
fetchSpots () {
    return api.get('spot')
  },

I know I'm incorrectly using corsHeaders wrong.
I would really appreciate it if someone could explain how to do authorization with headers from axios to claudia back-end

I really appreciate any help. Thanks so much!

Environment variable aka stage dev/prod

Hi,
I've seen how to figure out if a lambda is in 'dev' or 'prod' from the main claudia.js repository.

exports.handler = function (event, context) {
	var alias = context.invokedFunctionArn.replace(/.*:/g,'');
	context.succeed('executing: ' + alias + ' (version ' + context.functionVersion + ')');
};

What I'd like to do it's the same for an APIBuilder project.

The reason behind this is: something you need to wrap your code (for example, we use IOPipe) but at the same time there are variables that are 'stage' bound and apply to all endpoints, with no context or request.

Removing all routes, this is our setup:

const api = new ApiBuilder({ mergeVars: true });
const iopipe = iopipeLib({
  token:
    'secretToken',
});

api.proxyRouter = iopipe(api.proxyRouter);

module.exports = api;

What we need is to distinguish prod and dev, passing a different token.

const iopipe = iopipeLib({
  token:
    process.env.iopipeToken,
});

Thanks

Use subresources for routing

I have not been able to figure out a way to set up a nested resource for e.g. "/greet/me". Is there a way to do this or is it a missing feature?

Documentation: What case do the keys in `request.headers` use?

The API docs page mentions that headers is a dictionary of headers but does not describe the format of the keys. Are they just as the caller specified them, or are they standardised to a particular case (such as first capital, rest lower case)? Thanks!

Log path to CloudWatch

First off, I love Claudia and claudia-api-builder! Kudos on an amazing project!!

One frustration I've noticed is with logging. AWS Lambda automatically logs requests to CloudWatch, but since claudia-api-builder sends all routes to the same Lambda, all the logs in CloudWatch are grouped under a single Lambda function. This makes it impossible to know which route was used to access the lambda without adding console.log inside every route handler. This latter option feels verbose as it seems this info should be logged by default.

Would a pull-request be amenable?

ApiBuilder.ApiResponse is not a constructor error @ claudia-api-builder v3.0.x

Using "claudia-api-builder": "^3.0.1":

The snippet below is supposed to return an error 400, but instead is throwing an internal server error.

const ApiBuilder = require('claudia-api-builder');
const api = new ApiBuilder();

api.get('/error', function () {
  return new ApiBuilder.ApiResponse({ message: 'Failed validation!' }, {'Content-Type': 'application/json'}, 400);
});
  • Expected behaviour:
    API returns an error 400 along with the error message.

  • What actually happens:
    HTTP status code is 500.

{
    "errorMessage": "ApiBuilder.ApiResponse is not a constructor"
}

Add options to `ApiResponse`

For the moment, it's not possible to pass contentHandling: 'CONVERT_TO_BINARY' to a new ApiResponse.

It could be a good option to have the possibility to add some configuration to a new ApiResponse.

module.exports.ApiResponse = function (response, headers, code) {
'use strict';
this.response = response;
this.headers = headers;
this.code = code;
};

Support for multiple path params

I have been experimenting with claudia / claudia API builder and it has been working rather well. One of our use cases requires a path that looks like: /user/{foo}/subresource/{bar}

When defining a path in the api builder with this format and running claudia update I am getting an error back:

[BadRequestException: Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end.

When I only define one dynamic path parameter, claudia will post to AWS just fine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.