This question already has answers here:
Axios get in url works but with second parameter as object it doesn't
(4 answers)
Closed 5 years ago.
I want to send a get request with an object. The object data will be used on the server to update session data. But the object doesn't seem to be sent correctly, because if I try to send it back to print it out, I just get:
" N; "
I can do it with jQuery like this and it works:
$.get('/mysite/public/api/updatecart', { 'product': this.product }, data => {
console.log(data);
});
The object is sent back from server with laravel like this:
public function updateCart(Request $request){
return serialize($request->product);
The same thing doesn't work with axios:
axios.get('/api/updatecart', { 'product': this.product })
.then(response => {
console.log(response.data);
});
I set a default baseURL with axios so the url is different. It reaches the api endpoint correctly and the function returns what was sent in, which was apparently not the object. I only get "N; " as result.
Axios API is a bit different from the jQuery AJAX one. If you have to pass some params along with GET request, you need to use params property of config object (the second param of .get() method):
axios.get('/api/updatecart', {
params: {
product: this.product
}
}).then(...)
You can pass either a plain object or a URLSearchParams object as params value.
Note that here we're talking about params appended to URL (query params), which is explicitly mentioned in the documentation.
If you want to send something within request body with GET requests, params won't work - and neither will data, as it's only taken into account for PUT, POST, DELETE, and PATCH requests. There're several lengthy discussions about this feature, and here's the telling quote:
Unfortunately, this doesn't seem to be an axios problem. The problem
seems to lie on the http client implementation in the browser
javascript engine.
According to the documentation and the spec XMLHttpRequest ignores the
body of the request in case the method is GET. If you perform a
request in Chrome/Electron with XMLHttpRequest and you try to put a
json body in the send method this just gets ignored.
Using fetch which is the modern replacement for XMLHtppRequest also
seems to fail in Chrome/Electron.
Until it's fixed, the only option one has within a browser is to use POST/PUT requests when data just doesn't fit into that query string. Apparently, that option is only available if corresponding API can be modified.
However, the most prominent case of GET-with-body - ElasticSearch _search API - actually does support both GET and POST; the latter seems to be far less known fact than it should be. Here's the related SO discussion.
Related
I have built something that can capture network requests and save them to a file. Currently I am now trying to build the second part which should return these captured requests, but running into some difficulties. Sometimes I have multiple requests going to a single method/url combination, and I need to return a different response depending on the request body. The problem I am facing is illustrated in the example below:
cy.route({
url: 'api.example.com/**',
method: myMethod,
response: routeData => {
// I can set the response here
// But I don't have access to the request body
},
onRequest: xhr => {
// I can access the request body here
// But I am not supposed/able to set the response
},
})
If I understand the API docs correctly, I am supposed to set the response in the response callback. However, in that callback I do not seem to have access to the XHR object from which I could read the request body.
Is there a way to access the request body in the response callback?
Or, alternatively, is there a way to set the response from the onRequest callback?
Update: just saw this post which mentions a body property which can be added to the cy.route options object. I don't see this in the cypress route docs so I don't know if this is even a valid option, and I also wouldn't know if making multiple calls to cy.route with an identical method and url, but a different body would produce the correct results. If this was of any use, I would have hoped to have seen some branching logic based on a body property somewhere in this file, so I am not super hopeful.
Cypress v6 comes with the cy.intercept API. Using that is much more convenient than using cy.server and cy.route.
It's my first time using AJAX and I don't understand why I need to specify url parameter in a JS Ajax call.
{% block javascript %}
<script>
$("#id_username").change(function () {
$.ajax({
url: '/some_new_url/',
data: {
'something': ...
},
success: function (data) {
if (data.is_taken) {
alert("Data is already in DB");
}
}
});
});
</script>
{% endblock %}
To my understanding, AJAX is used to do something on the server side without refreshing a page. So it shouldn't redirect to a new url upon sending a data to the server, and stay on the same url. And yet AJAX call requires url parameter.
And I don' really like this, because setting a new url means I have to add another url pattern in my app/urls.py.
re_path(r'^create/$', views.Some_View.as_view(), name='create'),
And as a consequence, make another view in my views.py
class Some_View(ListView):
model = SomeModel
fields = '__all__'
But, I already have a CBV that generates form fields on the user side and accepts user inputs. I only want to make my existing CBV to save data to DB using AJAX call.
Since I don't understand what the purpose of the url is, I don't know how to set up my new url pattern, and CBV. Can I get some explanation here?
++ This is just a bonus question, but my ultimate goal is to generate multiple form fields, and multiple Submit buttons that sends the respective form input data to the server using AJAX. If there's any advice on how to tweak AJAX code, I would appreciate it.
An AJAX request is just a regular HTTP request to a url on the server. The only difference between an AJAX request and a request made by an ordinary browser GET or POST is that with AJAX, the results that come back from the server are returned to your javascript function and then you get to decide what to do with those results.
So there's no automatic updating of anything.
If you want to save something on the server, you need a view there on the server which is capable of understanding the data you are sending in the AJAX request, saving it, and then sending back a response which, again, your javascript code needs to be able to understand.
But if you already have a view which is capable of doing what you want, you can use it for your AJAX request, you just have to send a request with everything in it that the view requires.
I am making an ajax post request to the server, posting json data. In firebug I can see the network post call going through along with the json data.
In Laravel I was trying to do a simple var dump of the $_POST data and have just wasted a fair bit of time being confused as to why this should be completely empty. However, when I use the Request facade, my data is there.
ie. this just gives me an empty array:
public function test(){
Log::info($_POST);
}
...yet this prints my data, as I expect:
public function test(Request $request){
Log::info($request->all());
}
Why?
Edit
Thanks, #Webdesigner. The http verb is definitely post, as my method is called in my routes file via
Route::post('/image-upload', 'EntryController#test'); // Note "post" verb
I don't think $request->post() is valid in Laravel 5.4 as this throws an BadMethodCallException: Method post does not exist. error. However, I can confirm that
Log::info($request->method()); // POST
also tells me the method is post.
Very strange. I guess you're right that some part of the app is overwriting the $_POST global, though I have no idea why/where/how. Probably not relevant, but this call is being made from Angular 4.
Thanks for your help anyway!
This is not the normal behavior of Laravel. I tested this on a fresh Laravel 5.5 site and just did a Form submit and an Ajax POST request to the same Route.
Both give me the same result. A POST Request should have at least the CSRF Token as _token with a value.
One other point is $request->all() is not only the the content of $_POST so to have a fair compression you should try $request->post().
BTW only because you did a POST request do not mean that the data is send by the POST Method, it could be that the data you see in $request->all() is from $_GET and $_COOKIE, etc and only the Method was a POST.
Last but not least there it the option that some part of your APP is deleting the content of the Superglobal Variables. $_POST and the others are not like constants, so they can be changed during runtime e.g. $_POST = [];
I don't thing that there is a difference in Laravel 5.4.27.
How can I customize $http in angularjs such that it will accept strings as its response in a $http.post call? Right now, when I do a $http.post call, my response is in string but angularjs by default uses JSON therefore I get an error. Right now I have something along the lines of
function getResponseURL(response) {
//this will convert the response to string
return response;
}
$http.defaults.transformResponse = [];
$http.defaults.transformResponse.unshift(getResponseURL);
However if I use the code above, any $http.post calls after that call uses string. I want it to use the original default JSON format. How can I go about into just temporarily changing the response to string for this one call but the rest stay as JSON type as a response?
Why not only register that transform for ONLY that request?
Angular js $http docs
If you wish
override the request/response transformations only for a single
request then provide transformRequest and/or transformResponse
properties on the configuration object passed into $http.
I'm messing around with Django and AngularJS, attempting to send data back to my server using the $http resource. It looks like I could do this by either posting the data back as a form by setting the content-type as follows:
$http({
url: url,
data: form_encoded_data,
method: 'POST',
headers : {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
});
Or post back JSON in the request body with something like this:
$http.post(url, json_data)
.success(function(data, status, headers, config) {
...
}
In the first method, I can get access to the form data in my Django view via request.POST, and in the second, I can get access to the JSON via request.body. They both seem to work, but what's considered best practice?
I'm not sure what the convention for JSON data is. What I am sure of is that there is a convention for getting form data. In the absence of a compelling reason to use JSON, I would tend to think it's better to stick with the request.POST
I would go with using a form, it just makes sense intuitively and it is what I have used every time.
I prefer to use the $http service that accepts an object literal for configuration:
$http({method:'POST',url:'api/customers/add', data: customer})
.success(function(data) {
...
});
The result is promise object where you can immediately call .success. Its cleaner and easier to read IMO.
Note: customer is typically a data-bound object literal in JSON notation, but it does not have to be.