-
-
Save czerasz/4557315 to your computer and use it in GitHub Desktop.
Get Varnish to handle JSONP requests - working example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
backend jsonp_varnish { | |
.host = "localhost"; | |
.port = "80"; | |
} | |
#------------- begin jsonp functionality -------------# | |
# How the jsonp_template_backend dispatches to the ESI generating code: | |
sub jsonp_throw_error_recv { | |
if (req.url == "/JSONP-ESI-TEMPLATE") { | |
error 760; | |
} | |
} | |
sub jsonp_prepare_request_recv { | |
# If URL includes callback=, rewrite to an ESI template | |
if (req.url ~ "callback=\S") { | |
set req.http.X-Callback = regsub( | |
req.url, ".*[\?&]callback=([\.A-Za-z0-9_\[\]]+).*", "\1" | |
); | |
set req.http.X-ESI-Url = regsub(req.url, "&?callback=[\.A-Za-z0-9_\[\]]+", ""); | |
# Remove a trailing ? | |
set req.http.X-ESI-Url = regsub(req.http.X-ESI-Url, "\?$", ""); | |
# Fix any accidental ?& | |
set req.http.X-ESI-Url = regsub(req.http.X-ESI-Url, "\?&", "?"); | |
set req.url = "/JSONP-ESI-TEMPLATE"; | |
# We go BACK to varnish to get it to generate an ESI template that | |
# generates a JSON-P response. | |
set req.backend = jsonp_varnish; | |
return (pass); # NEVER cache template, since it varies on X-Callback/ESI-Url | |
} | |
} | |
sub jsonp_begin_esi_fetch { | |
# X-ESI: 1 from backend triggers ESI processing | |
if (beresp.http.X-ESI) { | |
remove beresp.http.X-ESI; | |
set beresp.do_esi = true; | |
} | |
} | |
sub jsonp_clean_fetch { | |
# X-JSONP-Server means we need to clean up the response a bit | |
if (beresp.http.X-JSONP-Server) { | |
remove beresp.http.X-JSONP-Server; | |
remove beresp.http.Via; # Gets added again later on, but a bit less messy | |
remove beresp.http.Retry-After; | |
set beresp.http.Server = "JSONP-Server"; | |
} | |
} | |
# We're using a custom error here because it's the only way I could find to get | |
# varnish to compose a custom response. | |
sub vcl_error { | |
if (obj.status == 760) { | |
set obj.http.Content-Type = "application/javascript"; | |
set obj.http.X-ESI = "1"; | |
set obj.http.X-JSONP-Server = "1"; | |
set obj.status = 200; | |
set obj.response = "OK"; | |
synthetic | |
"<esi:include />" + # Blank directive, needed to avoid this error: ESI_xmlerror: No ESI processing, first char not '<' | |
req.http.X-Callback + | |
{"(<esi:include src="http://your.domain.com"} + req.http.X-ESI-Url + {"" />);"}; | |
return(deliver); | |
} | |
} | |
#------------- end jsonp functionality -------------# | |
sub vcl_recv { | |
call jsonp_throw_error_recv; | |
call jsonp_prepare_request_recv; | |
} | |
sub vcl_fetch { | |
call jsonp_begin_esi_fetch; | |
call jsonp_clean_fetch; | |
# Add this if You use gzip compression for Your json assets | |
if ( beresp.http.content-type ~ "application/javascript" ) { | |
set beresp.do_gzip = true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It was a great help! Thx! :)