lib/assets/javascripts/up/proxy.js.coffee in upjs-rails-0.17.0 vs lib/assets/javascripts/up/proxy.js.coffee in upjs-rails-0.18.0
- old
+ new
@@ -86,25 +86,38 @@
You might find it useful to set this to `1` in full-stack integration
tests (e.g. Selenium).
Note that your browser might [impose its own request limit](http://www.browserscope.org/?category=network)
regardless of what you configure here.
+ @param {Array<String>} [config.wrapMethods]
+ An array of uppercase HTTP method names. AJAX requests with one of these methods
+ will be converted into a `POST` request and carry their original method as a `_method`
+ parameter. This is to [prevent unexpected redirect behavior](https://makandracards.com/makandra/38347).
+ @param {String} [config.wrapMethodParam]
+ The name of the POST parameter when wrapping HTTP methods in a `POST` request.
+ @param {Array<String>} [config.safeMethods]
+ An array of uppercase HTTP method names that are considered idempotent.
+ The proxy cache will only cache idempotent requests and will clear the entire
+ cache after a non-idempotent request.
@stable
###
config = u.config
busyDelay: 300
preloadDelay: 75
cacheSize: 70
cacheExpiry: 1000 * 60 * 5
maxRequests: 4
+ wrapMethods: ['PATCH', 'PUT', 'DELETE']
+ wrapMethodParam: '_method'
+ safeMethods: ['GET', 'OPTIONS', 'HEAD']
cacheKey = (request) ->
normalizeRequest(request)
[ request.url,
request.method,
request.data,
- request.selector
+ request.target
].join('|')
cache = u.cache
size: -> config.cacheSize
expiry: -> config.cacheExpiry
@@ -123,15 +136,15 @@
@experimental
###
get = (request) ->
request = normalizeRequest(request)
candidates = [request]
- unless request.selector is 'html'
- requestForHtml = u.merge(request, selector: 'html')
+ unless request.target is 'html'
+ requestForHtml = u.merge(request, target: 'html')
candidates.push(requestForHtml)
- unless request.selector is 'body'
- requestForBody = u.merge(request, selector: 'body')
+ unless request.target is 'body'
+ requestForBody = u.merge(request, target: 'body')
candidates.push(requestForBody)
for candidate in candidates
if response = cache.get(candidate)
return response
@@ -139,11 +152,11 @@
Manually stores a promise for the response to the given request.
@function up.proxy.set
@param {String} request.url
@param {String} [request.method='GET']
- @param {String} [request.selector='body']
+ @param {String} [request.target='body']
@param {Promise} response
A promise for the response that is API-compatible with the
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
@experimental
###
@@ -156,11 +169,11 @@
automatically removes cache entries.
@function up.proxy.remove
@param {String} request.url
@param {String} [request.method='GET']
- @param {String} [request.selector='body']
+ @param {String} [request.target='body']
@experimental
###
remove = cache.remove
###*
@@ -198,11 +211,11 @@
normalizeRequest = (request) ->
unless request._normalized
request.method = u.normalizeMethod(request.method)
request.url = u.normalizeUrl(request.url) if request.url
- request.selector ||= 'body'
+ request.target ||= 'body'
request._normalized = true
request
###*
Makes a request to the given URL and caches the response.
@@ -219,28 +232,30 @@
be emitted.
@function up.proxy.ajax
@param {String} request.url
@param {String} [request.method='GET']
- @param {String} [request.selector='body']
+ @param {String} [request.target='body']
@param {Boolean} [request.cache]
Whether to use a cached response, if available.
If set to `false` a network connection will always be attempted.
@param {Object} [request.headers={}]
An object of additional header key/value pairs to send along
with the request.
+ @param {Object} [request.data={}]
+ An object of request parameters.
@return
A promise for the response that is API-compatible with the
promise returned by [`jQuery.ajax`](http://api.jquery.com/jquery.ajax/).
@stable
###
ajax = (options) ->
forceCache = (options.cache == true)
ignoreCache = (options.cache == false)
- request = u.only(options, 'url', 'method', 'data', 'selector', 'headers', '_normalized')
+ request = u.only(options, 'url', 'method', 'data', 'target', 'headers', '_normalized')
pending = true
# Non-GET requests always touch the network
# unless `options.cache` is explicitly set to `true`.
@@ -274,12 +289,10 @@
loadStarted()
promise.always(loadEnded)
promise
- SAFE_HTTP_METHODS = ['GET', 'OPTIONS', 'HEAD']
-
###*
Returns `true` if the proxy is not currently waiting
for a request to finish. Returns `false` otherwise.
The proxy will also emit an [`up:proxy:idle` event](/up:proxy:idle) if it
@@ -370,13 +383,29 @@
request: request
queuedRequests.push(entry)
deferred.promise()
load = (request) ->
- u.debug('Loading URL %o', request.url)
+ u.debug('Fetching %o via %o', request.url, request.method)
up.emit('up:proxy:load', request)
- promise = u.ajax(request)
+
+ # We will modify the request below for features like method wrapping.
+ # Let's not change the original request which would confuse API clients
+ # and cache key logic.
+ request = u.copy(request)
+
+ request.headers ||= {}
+ request.headers['X-Up-Target'] = request.target
+ request.data = u.requestDataAsArray(request.data)
+
+ if u.contains(config.wrapMethods, request.method)
+ request.data.push
+ name: config.wrapMethodParam
+ value: request.method
+ request.method = 'POST'
+
+ promise = $.ajax(request)
promise.always ->
up.emit('up:proxy:received', request)
pokeQueue()
promise
@@ -391,27 +420,27 @@
is starting to load.
@event up:proxy:load
@param event.url
@param event.method
- @param event.selector
+ @param event.target
@experimental
###
###*
This event is [emitted]/(up.emit) when the response to an [AJAX request](/up.proxy.ajax)
has been received.
@event up:proxy:received
@param event.url
@param event.method
- @param event.selector
+ @param event.target
@experimental
###
isIdempotent = (request) ->
normalizeRequest(request)
- u.contains(SAFE_HTTP_METHODS, request.method)
+ u.contains(config.safeMethods, request.method)
checkPreload = ($link) ->
delay = parseInt(u.presentAttr($link, 'up-delay')) || config.preloadDelay
unless $link.is($waitingLink)
$waitingLink = $link