Skip to content
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

How to set CORS on per endpoint basis? #114

Closed
dondyb opened this issue Nov 27, 2015 · 7 comments
Closed

How to set CORS on per endpoint basis? #114

dondyb opened this issue Nov 27, 2015 · 7 comments
Labels

Comments

@dondyb
Copy link

dondyb commented Nov 27, 2015

Hi,

Any idea on how to enable CORS or set Header on per end point basis ? If I use middleware it will be for all request, won't it ?

Thanks in advance

@timothycrosley
Copy link
Collaborator

Hi @dondyb,

Happy holidays! Yes, a middleware will make it be for all requests, here's how you could do it for a single API endpoint:

@hug.get()
def my_api_endpoint(response=None, ...otherargs):
    response and response.set_header('Access-Control-Allow-Origin', '*')

Or, if you want to make it in a reusable fashion you could do one of the following:

A requires function:

def cors_support(response, *args, **kwargs):
    response.set_header('Access-Control-Allow-Origin', '*')


@hug.get(requires=cors_support)
def my_api_endpoint(...otherargs):
    pass


@hug.get(requires=cors_support)
def my_api_endpoint_2(...otherargs):
    pass

Or, if you want to be really fancy, you could use a directive:

@hug.directive()
def cors(support='*', response=None, **kwargs):
    '''Returns passed in parameter multiplied by itself'''
    response and response.set_header('Access-Control-Allow-Origin', support)


@hug.get()
def my_api_endpoint(hug_cors, ...otherargs):
    pass


@hug.get()
def my_api_endpoint_2(hug_cors='http://onlythisdomain.com', ...otherargs):
    pass

Let me know if this answeres your question.

Thanks!

~Timothy

@dondyb
Copy link
Author

dondyb commented Dec 1, 2015

Hi @timothycrosley,

Thanks. It does work. Didn't realize if that simple 💃

@nongiach
Copy link

nongiach commented Mar 21, 2017

hey,
if you are like me all 3 options above is not what you need,
these could be what you want.

@hug.response_middleware()
def process_data(request, response, resource):
      response.set_header('Access-Control-Allow-Origin', '*')

it adds the header too all request, even 404, 405...
someone even made a module of it but maybe it's too much ^^.
https://pypi.python.org/pypi/hug-middleware-cors/1.0.0

@radumas
Copy link

radumas commented Sep 20, 2017

Hi @timothycrosley, two questions related to this question:

  1. Is this in the documentation? I ran into a CORS issue almost immediately using hug.
  2. Is there a way/need of making the below code more restrictive than a wildcard? I'm not super familiar with CORS but from Googling this morning trying to solve this issue it seems like '*' isn't best practice.

@danigosa
Copy link

danigosa commented Nov 7, 2017

@radumas the '*' is a generic solution, if you want to have fine-grained access control this unfortunately will be bound to your application specifics, therefore in any case documenting it's not very helpful, as this is beyond the hug's (or underlying falcon) responsibility.

Here a more complete, almost production sample we use, for generic permissive access, two options:

1. Pure hug middleware

@hug.response_middleware()
def CORS(request, response, resource):
    response.set_header('Access-Control-Allow-Origin', '*')
    response.set_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
    response.set_header(
        'Access-Control-Allow-Headers',
        'Authorization,Keep-Alive,User-Agent,'
        'If-Modified-Since,Cache-Control,Content-Type'
    )
    response.set_header(
        'Access-Control-Expose-Headers',
        'Authorization,Keep-Alive,User-Agent,'
        'If-Modified-Since,Cache-Control,Content-Type'
    )
    if request.method == 'OPTIONS':
        response.set_header('Access-Control-Max-Age', 1728000)
        response.set_header('Content-Type', 'text/plain charset=UTF-8')
        response.set_header('Content-Length', 0)
        response.status_code = hug.HTTP_204

2. You don't want to mess hug up with constant middleware, use nginx:

# You've already set server properties before...
# Serve Hug API
    location / {
           add_header 'Access-Control-Allow-Origin' '*';
           add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
           add_header 'Access-Control-Allow-Headers' 'Authorization,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,Content-Type';
           add_header 'Access-Control-Expose-Headers' 'Authorization,Keep-Alive,User-Agent,If-Modified-Since,Cache-Control,Content-Type';
           if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
           }
# Here is were you proxy_pass or uwsgi_pass to wsgi server...

@sameh-sharaf
Copy link

@danigosa this is a great answer. Wish this would be documented somewhere so people don't spend days looking for a solution.

@timothycrosley
Copy link
Collaborator

@sameh-sharaf good call! I've added an initial answer to this question on the projects FAQ documentation to start: https://hugapi.github.io/hug/FAQ/

I apologize for the documentation gap!

~Timothy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants