Skip to content

Commit

Permalink
Allow Ajax.Request to use any HTTP verb without the antiquated `_me…
Browse files Browse the repository at this point in the history
…thod=` URL fallback. (Closes #280)
  • Loading branch information
savetheclocktower committed Apr 8, 2017
1 parent f63d7f7 commit 5140d0c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
8 changes: 5 additions & 3 deletions src/prototype/ajax.js
Expand Up @@ -42,6 +42,9 @@
* `XMLHttpRequest` is used asynchronously or not. Synchronous usage is
* **strongly discouraged** — it halts all script execution for the
* duration of the request _and_ blocks the browser UI.
* * `body` ([[String]]): Specific contents for the request body on a
* method that sends a payload (like `post` or `put`). If it is not
* provided, the contents of the `parameters` option will be used instead.
* * `contentType` ([[String]]; default `application/x-www-form-urlencoded`):
* The `Content-type` header for your request. Change this header if you
* want to send data in another format (like XML).
Expand All @@ -57,9 +60,8 @@
* encoded into the URL for a `get` method, or into the request body for the
* other methods. This can be provided either as a URL-encoded string, a
* [[Hash]], or a plain [[Object]].
* * `postBody` ([[String]]): Specific contents for the request body on a
* `post` method. If it is not provided, the contents of the `parameters`
* option will be used instead.
* * `postBody` ([[String]]): An alias for `body` that is provided for
* backward-compatibility. Its use is discouraged.
* * `requestHeaders` ([[Object]]): A set of key-value pairs, with properties
* representing header names.
* * `evalJS` ([[Boolean]] | [[String]]; default `true`): Automatically `eval`s
Expand Down
15 changes: 7 additions & 8 deletions src/prototype/ajax/request.js
Expand Up @@ -183,12 +183,6 @@ Ajax.Request = Class.create(Ajax.Base, {
this.options.parameters :
Object.toQueryString(this.options.parameters);

if (!['get', 'post'].include(this.method)) {
// simulate other verbs over post
params += (params ? '&' : '') + "_method=" + this.method;
this.method = 'post';
}

if (params && this.method === 'get') {
// when GET, append parameters to URL
this.url += (this.url.include('?') ? '&' : '?') + params;
Expand All @@ -209,7 +203,12 @@ Ajax.Request = Class.create(Ajax.Base, {
this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();

this.body = this.method == 'post' ? (this.options.postBody || params) : null;
if (this.method !== 'get') {
this.body = this.options.body || this.options.postBody || params;
} else {
this.body = null;
}

this.transport.send(this.body);

/* Force Firefox to handle ready state 4 for synchronous requests */
Expand All @@ -235,7 +234,7 @@ Ajax.Request = Class.create(Ajax.Base, {
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};

if (this.method == 'post') {
if (this.method !== 'get') {
// Don't set the `Content-Type` header if the user has explicitly set
// `contentType` to anything falsy.
if (this.options.contentType) {
Expand Down
8 changes: 7 additions & 1 deletion test/unit/server.rb
Expand Up @@ -54,6 +54,12 @@ class UnitTests < Sinatra::Application
})
end

# The '/inspect' endpoint should be available regardless of HTTP method.
def self.handle_inspect(url, &block)
%w{get post put delete patch options head}.each do |verb|
self.send(verb, url, &block)
end
end

def self.get_or_post(url, &block)
get(url, &block)
Expand Down Expand Up @@ -108,7 +114,7 @@ def self.get_or_post(url, &block)

# Routes for Ajax tests

get_or_post '/inspect' do
handle_inspect '/inspect' do
response = {
:headers => request_headers(request.env),
:method => request.request_method,
Expand Down
35 changes: 34 additions & 1 deletion test/unit/tests/ajax.test.js
Expand Up @@ -269,7 +269,7 @@ suite("Ajax", function () {
assert.equal('Hello world!', h2.innerHTML);
});

test('Content-Type set for simulated verbs', function () {
test('Content-Type set for obscure verbs', function () {
new Ajax.Request('/inspect', extendDefault({
method: 'put',
contentType: 'application/bogus',
Expand All @@ -282,6 +282,39 @@ suite("Ajax", function () {
}));
});

test('verbs with bodies', function () {
var verbs = $w('post put patch');
verbs.each(function (verb) {
new Ajax.Request('/inspect', extendDefault({
method: verb,
body: 'foo=foo&bar=bar',
onSuccess: function (response) {
var body = response.responseJSON.body;
assert.equal('foo=foo&bar=bar', body, verb + ' should send body');
},
onFailure: function () {
assert(false, verb + ' should send body');
}
}));
});
});

test('verbs without bodies', function () {
var verbs = $w('get head options delete');

verbs.each(function (verb) {
new Ajax.Request('/inspect', extendDefault({
method: verb,
onSuccess: function () {
assert(true, verb + ' method should work');
},
onFailure: function () {
assert(false, verb + ' method should work');
}
}));
});
});

test('onCreate callback', function () {
new Ajax.Request('/fixtures/content.html', extendDefault({
onCreate: function (transport) {
Expand Down

0 comments on commit 5140d0c

Please sign in to comment.