Simplest possible app that handles CORS?

1,139 views
Skip to first unread message

Rob Willett

unread,
Apr 29, 2015, 7:44:45 AM4/29/15
to mojol...@googlegroups.com
Hi,

First time poster. 

We've written an app using jquery, Cordova and were trying too work out a simple REST server framework to use. Since we had a lot of code already written in JavaScript and using SQLite we thought we'd try express.js and the sqlite modules there. Whilst simple interactions seem to work, the asynchronous nature and the complete lack of sensible support for SQL transactions, we abandoned that and went back to our other option Mojolicious.

I've been reading a lot about Mojlicious and have struggled to find the answer to what I think should be a simple problem. We simply want to allow anybody to access the Mojlicious web app. Our app will be on our own intranet and we don't want anything in the way. 

We thought this would be simple but we seem to be struggling with this and after reading vast quantities of blogs, cpan sections we still cannot get a simple browser running Firefox to make a simple POST request to a Mojlicious server. We are embarrassed but after two days enough is enough, we're asking for help.

This is the smallest server code we could write.

#!/usr/bin/perl -w

use Mojolicious::Lite;

options '*' => sub {
  my $self = shift;

  $self->res->headers->header('Access-Control-Allow-Origin' => '*');
  $self->res->headers->header('Access-Control-Allow-Credentials' => 'true');
  $self->res->headers->header('Access-Control-Allow-Methods' => 'GET, OPTIONS, POST, DELETE, PUT');
  $self->res->headers->header('Access-Control-Allow-Headers' => 'Content-Type');
  $self->res->headers->header('Access-Control-Max-Age' => '1728000');

  $self->respond_to(any => { data => '', status => 200 });
};

get '/data' => sub {
    my $self = shift;

    print "GET found\n";
    $self->render(text => 'ok');
};

post '/data' => sub {
    my $self = shift;

    print "\nPOST found\n";
    $self->render(text => 'POST ok');
};

app->secrets(['My very secret passphrase.']);

app->start;

The code to call it from our app is

$http({
                    url: "http://localhost:3000/data" ,
                    method: 'POST' ,
                    headers: { 'Content-Type': 'application/json' } ,
                    data: { payload : payload }
                }).then(function(response) {
                    // Success
                    ConsoleLog("$http POST success");
       } ,
                function(response) {
                    ConsoleLog("$http POST failure");
});

We know this angular code works calling express.js running on node.js we we had it running, we extracted the JSON data from it and updated databases.

If we access this from curl, it works fine. 

curl --data "id=123" http://localhost:3000/data

We get 'POST OK' returned. 

If we access this from a Firefox browser, which we use as a development testing mule, we get 

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3000/data. This can be fixed by moving the resource to the same domain or enabling CORS.

We can see the OPTIONS method being called from the Network debugger under Firefox and it returns 200 which is OK. This is followed by a POST method and that looks OK as it returns 200. If we examine the headers it all 'looks ok' but clearly isn't. We can see that the debugging from the Mojlicious server prints out "Post found" which is what we would expect. 

We're sure this is something simple, but after a very long night and far too much coffee we've no idea what the problem is.

Any suggestions welcomed (including pack it all in and take up fishing).

Thanks

Rob


John

unread,
Apr 29, 2015, 7:47:38 AM4/29/15
to mojol...@googlegroups.com
I have not ready your entire post so don't know if this will apply in your case: Mojolicious::Plugin::CORS

John
--
You received this message because you are subscribed to the Google Groups "Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.
To post to this group, send email to mojol...@googlegroups.com.
Visit this group at http://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Rob Willett

unread,
Apr 29, 2015, 8:01:59 AM4/29/15
to mojol...@googlegroups.com
John,

Yes we looked at that and we tried it and couldn't get it to work either. 

We also tried the SecureCors version. 

We're struggling to understand why this is so difficult. Many, many people use this type of framework on the internet but as far as we can see very few people have his issue. There are very few code samples around either for us to try with which makes me think that somethings not quite right.

Thanks

Rob.

Rob Willett

unread,
Apr 29, 2015, 8:03:45 AM4/29/15
to mojol...@googlegroups.com
We also realise that our web skills are out of date and we are trying to bing ourselves up to date, but that takes time :(

Rob

Brian Duggan

unread,
Apr 29, 2015, 8:08:32 AM4/29/15
to mojol...@googlegroups.com
Hi Rob,

You'll want to send the CORS headers with requests other than OPTIONS,
e.g. a minimal example to enable it everywhere might be :

app->hook(after_dispatch => sub {
my $c = shift;
$c->res->headers->header('Access-Control-Allow-Origin' => '*');
}

Brian
> ><https://lh3.googleusercontent.com/-M5gnpxpeQzI/VUDDNTSXHnI/AAAAAAAAAHE/hgu5HgdWP9Q/s1600/Screen%2BShot%2B2015-04-29%2Bat%2B12.16.00.png>
> >
> >We're sure this is something simple, but after a very long night and far
> >too much coffee we've no idea what the problem is.
> >
> >Any suggestions welcomed (including pack it all in and take up fishing).
> >
> >Thanks
> >
> >Rob
> >
> >
> >--
> >You received this message because you are subscribed to the Google Groups
> >"Mojolicious" group.
> >To unsubscribe from this group and stop receiving emails from it, send an
> >email to mojolicious...@googlegroups.com
> ><mailto:mojolicious...@googlegroups.com>.
> >To post to this group, send email to mojol...@googlegroups.com
> ><mailto:mojol...@googlegroups.com>.

Rob Willett

unread,
Apr 29, 2015, 8:12:18 AM4/29/15
to mojol...@googlegroups.com
Brian,

Thanks for the comment. 

We thought that the OPTIONS command set the permissions up for the rest of the POST command, thats why there's a two-step process. It may well be that the version we had running under node.js did all of this under the covers. 

We'll plug that in and have a try.

Thanks for taking the time to reply.

Rob

Joe Landman

unread,
Apr 29, 2015, 8:25:32 AM4/29/15
to mojol...@googlegroups.com


On 04/29/2015 08:01 AM, Rob Willett wrote:
> John,
>
> Yes we looked at that and we tried it and couldn't get it to work either.
>
> We also tried the SecureCors version.
>
> We're struggling to understand why this is so difficult. Many, many
> people use this type of framework on the internet but as far as we can
> see very few people have his issue. There are very few code samples
> around either for us to try with which makes me think that somethings
> not quite right.

This is an issue with Grafana pre-2.0. They finally integrated a
dedicated server, which mirrors what we did to make it work (hide the
CORS dependent system behind nginx).

[...]

>> |
>>
>> $self->res->headers->header('Access-Control-Allow-Origin' => '*');
>> $self->res->headers->header('Access-Control-Allow-Credentials' =>
>> 'true');
>> $self->res->headers->header('Access-Control-Allow-Methods' =>
>> 'GET, OPTIONS, POST, DELETE, PUT');
>> $self->res->headers->header('Access-Control-Allow-Headers' =>
>> 'Content-Type');
>> |
>

Don't you want to include "Authorization" in the Allow-Headers ?

[...]

>> We can see the OPTIONS method being called from the Network
>> debugger under Firefox and it returns 200 which is OK. This is
>> followed by a POST method and that looks OK as it returns 200. If
>> we examine the headers it all 'looks ok' but clearly isn't. We
>> can see that the debugging from the Mojlicious server prints out
>> "Post found" which is what we would expect.
>>
>> <https://lh3.googleusercontent.com/-M5gnpxpeQzI/VUDDNTSXHnI/AAAAAAAAAHE/hgu5HgdWP9Q/s1600/Screen%2BShot%2B2015-04-29%2Bat%2B12.16.00.png>
>>
>> We're sure this is something simple, but after a very long night
>> and far too much coffee we've no idea what the problem is.
>>

I had a similar concept problem with InfluxDB that I had to debug. The
first thing I did is try a working server, and then "replace" it with a
very simple 'nc' command to listen on the port and spit out the received
client request. From there, I wrote a very simple client that generated
that same request (started with Mojo::Client, but for a specific reason,
moved to LWP::UserAgent).

The failure mode was that both Mojo::Client and LWP::UserAgent were
returning a 200 for the overall request, while the service was erroring
out without actually telling us. It turns out that error propagation in
web services is not simply remarkably bad, it is effectively
non-existent, and that 200, or other completion codes may or may not
have to do with the transport only. This was ... well ... a remarkable
observation, as I had been beating on the "why the heck is this failing"
horse for a few days, including some posts late last year here about
extracting error messages from chunked response queries. Short answer
is (and this one hurts), you can't get this data, with any reasonable
expectation of reasonableness, accuracy, etc. I am sure some will
disagree, but we saw this with not a small number of these web based
apps that we were working with trying to query/extract data/make useful.

You appear to be caught in a similar situation, albeit with CORS rather
than chunked response.

I'd recommend starting with a known working server and client. Replace
the server with an nc listening on that port, and dumping output to a file.
Write a client that generates that input (firefox and chrome were
effectively useless as debugging platforms until after I found the
issues and corrected them). Put the original server back in place. Make
sure the client still works. Put your new server in place, make sure
the client still works.

The upshot of this is we now have a very fast and powerful query tool
for our product. It just works, and we and our end users are happy with it.

>> Any suggestions welcomed (including pack it all in and take up
>> fishing).
>>
>> Thanks
>>
>> Rob
>>
>>
>> --
>> You received this message because you are subscribed to the
>> Google Groups "Mojolicious" group.
>> To unsubscribe from this group and stop receiving emails from it,
>> send an email to mojolicious...@googlegroups.com
>> <mailto:mojolicious...@googlegroups.com>.
>> To post to this group, send email to mojol...@googlegroups.com
>> <mailto:mojol...@googlegroups.com>.
>> Visit this group at http://groups.google.com/group/mojolicious.
>> For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Mojolicious" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to mojolicious...@googlegroups.com
> <mailto:mojolicious...@googlegroups.com>.
> To post to this group, send email to mojol...@googlegroups.com
> <mailto:mojol...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/mojolicious.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Mojolicious" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to mojolicious...@googlegroups.com
> <mailto:mojolicious...@googlegroups.com>.
> To post to this group, send email to mojol...@googlegroups.com
> <mailto:mojol...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/mojolicious.
> For more options, visit https://groups.google.com/d/optout.

--
Joe Landman
e: joe.l...@gmail.com
t: @sijoe

eiras...@gmail.com

unread,
Apr 29, 2015, 8:31:08 AM4/29/15
to mojol...@googlegroups.com
Hey Rob

Try adding 'Access-Control-Allow-Origin' (and 'Access-Control-Allow-Credentials') headers in your response to POST /data. Any shareble resource (POST /data in this case) must indicate at least which origin(s) the response may be shared with. Apart from issuing a preflight...

Hope it helps!

Brian Duggan

unread,
Apr 29, 2015, 8:32:31 AM4/29/15
to mojol...@googlegroups.com
Hi Rob,

My understanding is that if the user-agent sends OPTIONS (which it must
do only for a non-GET/HEAD/POST), then you go down this path :

http://www.w3.org/TR/cors/#cross-origin-request-with-preflight

which still reaches the "resource sharing check" :

http://www.w3.org/TR/cors/#resource-sharing-check

which starts out:

If the response includes zero or more than one
Access-Control-Allow-Origin header values, return fail and terminate
this algorithm.

Brian

Rob Willett

unread,
Apr 29, 2015, 8:37:39 AM4/29/15
to mojol...@googlegroups.com
Joe,

Thats very interesting what you say. I answer to your points:

1. Eventually we will have an Nginix server at the front end talking to this server. For development purposes we wanted to try things out locally without the hassle of a large amount of infrastructure and the headache of managing a vast quantity of IT to work out the SQL we need. 

2. We will look at Authorization in the headers. Our reading of it was that it was not needed, but happy to be proven completely wrong.

3. Your comment on 200 codes scares me, quite honestly. I had always assumed that the 200 codes meant that things were working correctly. We found a similar situation in express.js where begin and end database transactions were being completely ignored, that combined with complex async sql transaction meant that a delete from table might sometimes come after we have inserted the new data, thereby erasing our new data When we realised that the database transactions were no longer atomic, we simply said enough is enough and wanted to try Mojolicous out.

4. Your point on simplifying the end to end transaction is sound. We had started this with the move to the simplest web server we could make. We realise that curl isn't enough, so we might have to do what you suggest. After spending the last two days (and a lot of the night) beating our heads against a wall, we really wanted a simple suggestion :) The fact you think this is a powerful platform gives us hope.

Thanks for the helpful reply.

Rob

To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.
To post to this group, send email to mojol...@googlegroups.com.

Rob Willett

unread,
Apr 29, 2015, 10:02:46 AM4/29/15
to mojol...@googlegroups.com
All,

Thanks for all your help. We appear to have overcome the CORS hurdle and have something that at least is not giving a CORS error in Firefox which is more than we have had in the last 48 hours.

It turns out that you do need to send 'Access-Control-Allow-Origin' => '*' with the POST reply. It also turns out that a lot of the headers I was sending were not needed.

For posterity and because somebody else might find it useful, here is the full source code (that sounds rather grand for a hack), that works for us. It does nothing useful expect not throw an error.

#!/usr/bin/perl -w

use Mojolicious::Lite;

options '*' => sub {
    my $self = shift;

    $self->res->headers->header('Access-Control-Allow-Origin' => '*');
    #$self->res->headers->header('Access-Control-Allow-Credentials' => 'true');
    #$self->res->headers->header('Access-Control-Allow-Methods' => 'GET, OPTIONS, POST, DELETE, PUT');
    #$self->res->headers->header('Access-Control-Allow-Headers' => 'Content-Type');
    #$self->res->headers->header('Access-Control-Max-Age' => '1728000');

    $self->respond_to(any => { data => '', status => 200 });
};

get '/data' => sub {
    my $self = shift;

    print "GET found\n";
    $self->render(text => 'ok');
};

post '/data' => sub {
    my $self = shift;

    print "\nPOST 3 found\n";
    $self->render(text => 'POST ok' );
};

app->hook(after_dispatch => sub {
    my $c = shift;
    $c->res->headers->header('Access-Control-Allow-Origin' => '*');
          });

app->secrets(['My very secret passphrase.']);

app->start;

Note the commented lines in the options section. We've left them in as they may become useful. This is something we can build on, we wrote an awful lot of JavaScript which now needs converting to Perl.

Thanks again for all the help, hopefully I can do the same back some day.

Best wishes,

Rob.

Alex Efros

unread,
Apr 29, 2015, 11:29:13 AM4/29/15
to mojol...@googlegroups.com
Hi!

On Wed, Apr 29, 2015 at 01:01:57PM +0100, Rob Willett wrote:
> We also tried the SecureCors version.

This should work:

---cut---
#!/usr/bin/perl -w

use Mojolicious::Lite;

plugin 'SecureCORS', { max_age => 1728000 };

app->routes->cors('/data');

under '/data' => {
'cors.origin' => '*',
'cors.headers' => 'Content-Type',
};

get '/' => sub {
my $self = shift;

print "GET found\n";
$self->render(text => 'ok');
};

post '/' => sub {
my $self = shift;

print "\nPOST found\n";
$self->render(text => 'POST ok');
};

app->secrets(['My very secret passphrase.']);

app->start;
---cut---

Test it with:

curl -v -X OPTIONS -H 'Origin: site.tld' -H 'Access-Control-Request-Method: POST' http://localhost:3000/data
curl -v -H 'Origin: site.tld' --data "id=123" http://localhost:3000/data
curl -v -H 'Origin: site.tld' http://localhost:3000/data

--
WBR, Alex.

Rob Willett

unread,
Apr 29, 2015, 1:34:05 PM4/29/15
to mojol...@googlegroups.com
Alex,

I tried this and some things didn't work.  Deep down I'd like to use SecureCors as I feel its the 'right' thing to do.

This one appears to work

macpro:~ rwillett$ curl -v -X OPTIONS -H 'Origin: site.tld' -H 'Access-Control-Request-Method: POST' http://127.0.0.1:3000/data
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> OPTIONS /data HTTP/1.1
> User-Agent: curl/7.37.1
> Accept: */*
> Origin: site.tld
> Access-Control-Request-Method: POST
>
< HTTP/1.1 204 No Content
< Date: Wed, 29 Apr 2015 17:29:45 GMT
< Content-Length: 0
< Connection: keep-alive
* Server Mojolicious (Perl) is not blacklisted
< Server: Mojolicious (Perl)
< Content-Type: text/html;charset=UTF-8
<
* Connection #0 to host 127.0.0.1 left intact

[Wed Apr 29 18:29:27 2015] [debug] OPTIONS "/data"
[Wed Apr 29 18:29:27 2015] [debug] Routing to a callback
[Wed Apr 29 18:29:27 2015] [debug] 204 No Content (0.000504s, 1984.127/s)
[Wed Apr 29 18:29:45 2015] [debug] OPTIONS "/data"
[Wed Apr 29 18:29:45 2015] [debug] Routing to a callback
[Wed Apr 29 18:29:45 2015] [debug] 204 No Content (0.000465s, 2150.538/s)

This one fails

curl -v -H 'Origin: site.tld' --data "id=123" http://localhost:3000/data

[Wed Apr 29 18:31:17 2015] [debug] POST "/data"
[Wed Apr 29 18:31:17 2015] [debug] Template "not_found.development.html.ep" not found
[Wed Apr 29 18:31:17 2015] [debug] Template "not_found.html.ep" not found
[Wed Apr 29 18:31:17 2015] [debug] Rendering cached inline template "fd403ab55a4c875e35b42428816134c7"
[Wed Apr 29 18:31:17 2015] [debug] Rendering cached inline template "dd85456cf9f44e1e43bebae130a7f9df"
[Wed Apr 29 18:31:17 2015] [debug] 404 Not Found (0.004456s, 224.417/s)

as does this one

curl -v -H 'Origin: site.tld' http://localhost:3000/data

[Wed Apr 29 18:32:11 2015] [debug] GET "/data"
[Wed Apr 29 18:32:11 2015] [debug] Template "not_found.development.html.ep" not found
[Wed Apr 29 18:32:11 2015] [debug] Template "not_found.html.ep" not found
[Wed Apr 29 18:32:11 2015] [debug] Rendering cached inline template "fd403ab55a4c875e35b42428816134c7"
[Wed Apr 29 18:32:11 2015] [debug] Rendering cached inline template "dd85456cf9f44e1e43bebae130a7f9df"
[Wed Apr 29 18:32:11 2015] [debug] 404 Not Found (0.004497s, 222.370/s)


Both the last two command return an error web page as well.

Should the SecureCors need a use command?

Rob.

Alex Efros

unread,
Apr 29, 2015, 1:55:26 PM4/29/15
to mojol...@googlegroups.com
Hi!

On Wed, Apr 29, 2015 at 10:34:05AM -0700, Rob Willett wrote:
> I tried this and some things didn't work.

Are you sure you've tried exact example from my email?

> This one appears to work
...
> < HTTP/1.1 204 No Content
> < Date: Wed, 29 Apr 2015 17:29:45 GMT
> < Content-Length: 0
> < Connection: keep-alive
> * Server Mojolicious (Perl) is not blacklisted
> < Server: Mojolicious (Perl)
> < Content-Type: text/html;charset=UTF-8
> <
> * Connection #0 to host 127.0.0.1 left intact

No, it doesn't. Here is how it should looks like when it really works
(check extra headers in reply; cors.pl is exact copy&paste from my email):


$ perl cors.pl daemon
[Wed Apr 29 20:50:23 2015] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000
[Wed Apr 29 20:50:25 2015] [debug] OPTIONS "/data"
[Wed Apr 29 20:50:25 2015] [debug] Routing to a callback
[Wed Apr 29 20:50:25 2015] [debug] 204 No Content (0.000650s, 1538.462/s)


$ curl -v -X OPTIONS -H 'Origin: site.tld' -H 'Access-Control-Request-Method: POST' http://127.0.0.1:3000/data
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> OPTIONS /data HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.42.0
> Accept: */*
> Origin: site.tld
> Access-Control-Request-Method: POST
>
< HTTP/1.1 204 No Content
< Date: Wed, 29 Apr 2015 17:50:25 GMT
< Access-Control-Max-Age: 1728000
< Content-Length: 0
< Access-Control-Allow-Methods: POST
< Connection: keep-alive
< Vary: Origin
< Access-Control-Allow-Origin: site.tld
< Server: Mojolicious (Perl)
< Content-Type: text/html;charset=UTF-8
<
* Connection #0 to host 127.0.0.1 left intact

--
WBR, Alex.

Rob Willett

unread,
Apr 29, 2015, 3:26:04 PM4/29/15
to mojol...@googlegroups.com
Apologies, I cut and pasted the top section as I thought that was all that changed. I missed off changing the 

get '/data' => sub { 

to 

get '/' => sub {

and 

post '/data' => sub {

to

post '/' => sub {

That'll teach me to rush things :)

Yes, this appears to work. Have tried with your curl tests and with our app. 

Now all I have to do is 

1) Add SQLite access in, 

2) Rewrite all the code from JavaScript to Perl (again). 

3) Add in JSON conversion routines.

4) Write GPS point in polygon conversion routines.

5) Write test scripts.

6) Write documentation

7) Sleep

Thanks again, I appreciate the helpful comments and the amount of time that people have put in to assist me. I hope I can return the compliment one day.

Rob.

--
                        WBR, Alex.

Lachlan Deck

unread,
Apr 20, 2016, 5:39:28 PM4/20/16
to Mojolicious
Hi Rob and all,

I'm new to Mojolicious and am trying to take your example and make it work for authentication, but am missing something obvious as I keep getting a 404.

General:
  1. Request URL:
    http://localhost:3002/users/login
  2. Request Method:
    OPTIONS
  3. Status Code:
    404 Not Found
  4. Remote Address:

Response headers:
  1. HTTP/1.1 404 Not Found
    Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
    Access-Control-Allow-Credentials: true
    Date: Wed, 20 Apr 2016 21:11:06 GMT
    Access-Control-Allow-Origin: http://localhost:3000
    Access-Control-Allow-Methods: GET, OPTIONS, POST, DELETE, PUT
    Content-Length: 17915
    Access-Control-Max-Age: 1728000
    Content-Type: text/html;charset=UTF-8
    Server: Mojolicious (Perl)

Request headers:
  1. OPTIONS /users/login HTTP/1.1
    Host: localhost:3002
    Connection: keep-alive
    Access-Control-Request-Method: POST
    Origin: http://localhost:3000
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
    Access-Control-Request-Headers: accept, authorization, content-type
    Accept: */*
    Referer: http://localhost:3000/?adaptor=localhost:3002&api=localhost:8080
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

Here's the code:
use Mojolicious::Lite;
use Mojo::Util 'secure_compare';

options '*' => sub {
    my $self = shift;
    my $path = $self->req->url->to_abs->path;

    say "PATH: $path";

    $self->res->headers->header('Access-Control-Allow-Origin' => $self->req->headers->origin);
    $self->res->headers->header('Access-Control-Allow-Credentials' => 'true');
    $self->res->headers->header('Access-Control-Allow-Methods' => 'GET, OPTIONS, POST, DELETE, PUT');
    $self->res->headers->header('Access-Control-Allow-Headers' => 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
    $self->res->headers->header('Access-Control-Max-Age' => '1728000');

    $self->respond_to(any => { $path  => '', status => 200 });
};


post '/users/login' => sub {
    my $c = shift;

    say "Authentication attempt...";

    # Check for username "Bender" and password "rocks"                                                                                                                                     
    return $c->render(text => 'Hello Bender!')
        if secure_compare $c->req->url->to_abs->userinfo, 'Bender:rocks';

    # Require authentication                                                                                                                                                               
    $c->res->headers->www_authenticate('Basic');
    $c->render(text => 'Authentication required!', status => 401);
};



app->hook(after_dispatch => sub {
    my $c = shift;
    my $headers = $c->req->headers;
    my $origin = $headers->origin;
    say "Origin: $origin";

    $c->res->headers->header('Access-Control-Allow-Origin' => $origin);
          });

app->secrets(['My very secret passphrase.']);
app->start;



Any suggestions?

Thanks!

Lachlan.

Rob Willett

unread,
Apr 21, 2016, 12:54:37 PM4/21/16
to Mojolicious
Lachlan,

1. Have you read the entire thread rather than the code I posted at the top.  I'm mobile at the moment and its difficult to work out the thread and which code you are using.

2. Take out the authentication and get the code working without it. Then add authentication back in.

3. How are you calling things? If from IOS or Android there are other things with CSP you need to do.

Rob

--
You received this message because you are subscribed to the Google Groups "Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.
To post to this group, send email to mojol...@googlegroups.com.

Lachlan Deck

unread,
Apr 21, 2016, 11:28:41 PM4/21/16
to mojol...@googlegroups.com
Hi Rob,

got it working.

Yes, I had read the whole thread. I had wrongly assumed that the options response (data => ‘’) was related to the get /data path.
Stripping authentication, as you suggested, to get it working first was certainly helpful.

For posterity, here’s the working example:

#!/usr/bin/perl -w                                                                                                                                                                                 

use Mojolicious::Lite;
use Mojo::Util 'secure_compare';

options '*' => sub {
    my $c = shift;
    my $origin = $c->req->headers->origin;
    say "OPTION ORIGIN: $origin";


    $c->res->headers->header('Access-Control-Allow-Origin' => $origin);
    $c->res->headers->header('Access-Control-Allow-Credentials' => 'true');
    $c->res->headers->header('Access-Control-Allow-Methods' => 'GET, OPTIONS, POST, DELETE, PUT');
    $c->res->headers->header('Access-Control-Allow-Headers' => 'Content-Type');
    #$c->res->headers->header('Access-Control-Max-Age' => '1728000');                                                                                                                              

    $c->respond_to(any => { data => '', status => 200 });

};

post '/users/login' => sub {
    my $c = shift;

    print "GET found\n";
    $c->render(text => 'Hello!')

        if secure_compare $c->req->url->to_abs->userinfo, 'Bender:rocks';

    $c->res->headers->www_authenticate('Basic');
    $c->render(text => 'Authentication required!', status => 401);
};


app->hook(after_dispatch => sub {
    my $c = shift;
    my $origin = $c->req->headers->origin;
    say "HOOK ORIGIN: $origin";

    $c->res->headers->header('Access-Control-Allow-Origin' => $origin);
          });

app->secrets(['My very secret passphrase.']);
app->start;

$ curl -v -X OPTIONS -H 'Origin: site.tld' -H 'Access-Control-Request-Method: POST' http://127.0.0.1:3002/users/login


cheers,
Lachlan

Rob Willett

unread,
Apr 22, 2016, 2:15:11 AM4/22/16
to mojol...@googlegroups.com

Pleased it works

Reply all
Reply to author
Forward
0 new messages