summaryrefslogtreecommitdiffstats
path: root/archives/extend/2013-April/000077.html
blob: 1bbf7ad272342a356618cb0dfc19077908a422fd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
 <HEAD>
   <TITLE> [99s-extend] Response headers
   </TITLE>
   <LINK REL="Index" HREF="index.html" >
   <LINK REL="made" HREF="mailto:extend%40lists.ninenines.eu?Subject=Re%3A%20%5B99s-extend%5D%20Response%20headers&In-Reply-To=%3C3E75C3ED-9F52-495A-8E04-EF0A4667DB4E%40gmail.com%3E">
   <META NAME="robots" CONTENT="index,nofollow">
   <style type="text/css">
       pre {
           white-space: pre-wrap;       /* css-2.1, curent FF, Opera, Safari */
           }
   </style>
   <META http-equiv="Content-Type" content="text/html; charset=us-ascii">
   <LINK REL="Previous"  HREF="000076.html">
   <LINK REL="Next"  HREF="000078.html">
 </HEAD>
 <BODY BGCOLOR="#ffffff">
   <H1>[99s-extend] Response headers</H1>
    <B>Lee Sylvester</B> 
    <A HREF="mailto:extend%40lists.ninenines.eu?Subject=Re%3A%20%5B99s-extend%5D%20Response%20headers&In-Reply-To=%3C3E75C3ED-9F52-495A-8E04-EF0A4667DB4E%40gmail.com%3E"
       TITLE="[99s-extend] Response headers">lee.sylvester at gmail.com
       </A><BR>
    <I>Thu Apr  4 10:38:07 CEST 2013</I>
    <P><UL>
        <LI>Previous message: <A HREF="000076.html">[99s-extend] Response headers
</A></li>
        <LI>Next message: <A HREF="000078.html">[99s-extend] Bullet connection
</A></li>
         <LI> <B>Messages sorted by:</B> 
              <a href="date.html#77">[ date ]</a>
              <a href="thread.html#77">[ thread ]</a>
              <a href="subject.html#77">[ subject ]</a>
              <a href="author.html#77">[ author ]</a>
         </LI>
       </UL>
    <HR>  
<!--beginarticle-->
<PRE>Hi Christopher,

Thank you for that.  I will attempt to go through each piece today and solve the problem.  This is good advice; maybe it belongs in a blog post?  :-)

Thanks again,
Lee




On 3 Apr 2013, at 21:35, &quot;Phillips, Christopher&quot; &lt;<A HREF="https://lists.ninenines.eu/listinfo/extend">Christopher.Phillips at turner.com</A>&gt; wrote:

&gt;<i> 
</I>&gt;<i>  Sure. Right now, Cowboy doesn't parse the headers, but you can manually
</I>&gt;<i> parse them in your handler. I've got them working in my implementation
</I>&gt;<i> pretty well, I'll try and break it down a bit here.
</I>&gt;<i> 
</I>&gt;<i>  A good, basic overview of what the requests the browser will send, and
</I>&gt;<i> what your responses should look like, is here:
</I>&gt;<i> <A HREF="https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS">https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS</A>
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> HANDLING PRE-FLIGHTS -
</I>&gt;<i>  Pre-flights are the OPTION requests the browser automatically sends off
</I>&gt;<i> when you make a CORS request using a verb other than GET, or POST with one
</I>&gt;<i> of three acceptable content types. They're defined well in the above link.
</I>&gt;<i> 
</I>&gt;<i>  You can read off the requested headers the actual call wants to send in
</I>&gt;<i> the OPTIONS preflight with
</I>&gt;<i> 
</I>&gt;<i> 	{Headers, NewRequest } =
</I>&gt;<i> cowboy_req:header(&lt;&lt;&quot;access-control-request-headers&quot;&gt;&gt;, Request)
</I>&gt;<i> 
</I>&gt;<i>  Headers will either be the binary, or undefined. If the binary, you
</I>&gt;<i> either need to manually parse it and choose to allow/disallow the request
</I>&gt;<i> from continuing based on it, or, if you just want to allow all headers
</I>&gt;<i> trivially, just pipe that back into the request, a la -
</I>&gt;<i> 
</I>&gt;<i>        Request2 = 
</I>&gt;<i> cowboy_req:set_resp_header(&lt;&lt;&quot;access-control-allow-headers&quot;&gt;&gt;,
</I>&gt;<i> binary_to_list(Headers), NewRequest)
</I>&gt;<i> 
</I>&gt;<i>  (As a reminder, it can be undefined. You'll need to check for that
</I>&gt;<i> before passing it into the above. If it's undefined, you don't need to add
</I>&gt;<i> the access-control-allow-headers header).
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i>  As part of the pre-flight request, you also need to handle what methods
</I>&gt;<i> are allowed. This looks something like -
</I>&gt;<i> 
</I>&gt;<i> 	PreflightedRequest =
</I>&gt;<i> cowboy_req:set_resp_header(&lt;&lt;&quot;access-control-allow-methods&quot;&gt;&gt;, &lt;&lt;&quot;GET,
</I>&gt;<i> POST, DELETE, PUT&quot;&gt;&gt;, Request2)
</I>&gt;<i> 
</I>&gt;<i>  If I wanted to allow gets, posts, deletes, and puts. You can also choose
</I>&gt;<i> to read off the access-control-request-method header sent from the client,
</I>&gt;<i> but I don't see the point; your list of allowed methods doesn't need to
</I>&gt;<i> change based on that (the user is requesting a POST, why does that change
</I>&gt;<i> whether you allow a POST or not? But I digress).
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> FOR ALL CALLS (both pre-flights and the actual call)
</I>&gt;<i>  Respond with acceptable origin. If you want any domain to access this
</I>&gt;<i> resource (not advised, unless this is a public, readonly resource, but
</I>&gt;<i> good for testing), you can do -
</I>&gt;<i> 
</I>&gt;<i>  	NewRequest = 
</I>&gt;<i> cowboy_req:set_resp_header(&lt;&lt;&quot;access-control-allow-origin&quot;&gt;&gt;, &lt;&lt;&quot;*&quot;&gt;&gt;,
</I>&gt;<i> Request)
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i>  If you want to filter out the allowed domains, it looks like -
</I>&gt;<i> 
</I>&gt;<i> 	Origin = cowboy_req:header(&lt;&lt;&quot;origin&quot;&gt;&gt;, Request) %Get the origin that
</I>&gt;<i> the browser sent you
</I>&gt;<i> 
</I>&gt;<i>        %Do logic to check Origin, and any other data that would decide
</I>&gt;<i> whether this request is allowed; it will only apply on a CORS request from
</I>&gt;<i> another browser.
</I>&gt;<i> 
</I>&gt;<i> 	%If it passes, pass Origin back as the value for the
</I>&gt;<i> access-control-allow-origin header.
</I>&gt;<i>        NewRequest =
</I>&gt;<i> cowboy_req:set_resp_header(&lt;&lt;&quot;access-control-allow-origin&quot;&gt;&gt;, Origin,
</I>&gt;<i> Request)
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> FOR ONLY THE ACTUAL CALL
</I>&gt;<i>  If you want to send custom headers back to your Javascript client (or
</I>&gt;<i> read any standard header beyond content-type), you need to explicitly
</I>&gt;<i> allow them. This looks like (if I wanted to expose the 'server' header so
</I>&gt;<i> my client Javascript can see that it's Cowboy on the backend) -
</I>&gt;<i> 
</I>&gt;<i>  	ExposedHeaderRequest =
</I>&gt;<i> cowboy_req:set_resp_header(&lt;&lt;&quot;access-control-expose-headers&quot;&gt;&gt;,
</I>&gt;<i> &lt;&lt;&quot;server&quot;&gt;&gt;, Request)
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i>  That's basically it I believe. There is also a max age, and a allow
</I>&gt;<i> credentials header (which is really more of a require credentials);
</I>&gt;<i> they're pretty straightforwardly explained on that page I linked above,
</I>&gt;<i> but I haven't played with them personally.
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i>  Caveats I ran into were largely being aware that same domain requests do
</I>&gt;<i> NOT supply any of the CORS headers, not even the origin header (so you can
</I>&gt;<i> get undefined and have to handle those cases), as well as understanding
</I>&gt;<i> the ramifications of allowing cross domain requests. Also, if you want to
</I>&gt;<i> develop while disconnected (or if it's not easy to grab another domain),
</I>&gt;<i> use your hosts file to declare a fake domain pointed to 127.0.0.1, load
</I>&gt;<i> your page from that, explicitly define your AJAX calls to localhost. Note
</I>&gt;<i> too that there is a bug in Firefox at present when you try and get all the
</I>&gt;<i> request headers. It returns an empty list. You can get individual ones if
</I>&gt;<i> you know the name (I.e., getResponseHeader(&quot;server&quot;) will work,
</I>&gt;<i> getAllResponseHeaders() returns an empty string). This is further
</I>&gt;<i> compounded by jQuery building its own XHR that loads headers by calling
</I>&gt;<i> getAllResponseHeaders, so in Firefox, using jQuery, you can get back zero
</I>&gt;<i> headers. Don't know if that affects you, but it's an issue it took me a
</I>&gt;<i> good while to diagnose, and which we've had to bear in mind.
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> On 4/3/13 3:33 PM, &quot;Lee Sylvester&quot; &lt;<A HREF="https://lists.ninenines.eu/listinfo/extend">lee.sylvester at gmail.com</A>&gt; wrote:
</I>&gt;<i> 
</I>&gt;&gt;<i> Hi list,
</I>&gt;&gt;<i> 
</I>&gt;&gt;<i> I'd like to set up my handler to use CORS.  Can anyone tell me how I can
</I>&gt;&gt;<i> modify the headers for my handler to support this?
</I>&gt;&gt;<i> 
</I>&gt;&gt;<i> Thanks loads,
</I>&gt;&gt;<i> Lee
</I>&gt;&gt;<i> _______________________________________________
</I>&gt;&gt;<i> Extend mailing list
</I>&gt;&gt;<i> <A HREF="https://lists.ninenines.eu/listinfo/extend">Extend at lists.ninenines.eu</A>
</I>&gt;&gt;<i> <A HREF="http://lists.ninenines.eu:81/listinfo/extend">http://lists.ninenines.eu:81/listinfo/extend</A>
</I>&gt;&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> 
</I>&gt;<i> _______________________________________________
</I>&gt;<i> Extend mailing list
</I>&gt;<i> <A HREF="https://lists.ninenines.eu/listinfo/extend">Extend at lists.ninenines.eu</A>
</I>&gt;<i> <A HREF="http://lists.ninenines.eu:81/listinfo/extend">http://lists.ninenines.eu:81/listinfo/extend</A>
</I>

</PRE>

<!--endarticle-->
    <HR>
    <P><UL>
        <!--threads-->
	<LI>Previous message: <A HREF="000076.html">[99s-extend] Response headers
</A></li>
	<LI>Next message: <A HREF="000078.html">[99s-extend] Bullet connection
</A></li>
         <LI> <B>Messages sorted by:</B> 
              <a href="date.html#77">[ date ]</a>
              <a href="thread.html#77">[ thread ]</a>
              <a href="subject.html#77">[ subject ]</a>
              <a href="author.html#77">[ author ]</a>
         </LI>
       </UL>

<hr>
<a href="https://lists.ninenines.eu/listinfo/extend">More information about the Extend
mailing list</a><br>
</body></html>