Best way to replace left and right parenths in a Get request - javascript

For my GET request, my server is rejecting it with status: 403, "HTTP/1.1 403 Forbidden"
My GET request object as is follows :
"{"method":"GET","url":"api/myapi/GETstuff","params":{"from":"2017-06-02","to":"2017-06-02","myData":"DATA (AND SOME/MORE DATA)"}}"
The javascript code is:
function getMyData(params){
var url = 'myapi/getStuff';
var req = {
method: 'GET',
url: url,
params: params
};
$http(req) // details omitted for brevity
.success()
.error();
}
I believe the problem is special characters send to the IIS server (such as parenths, and / char), which I need to encode the params array before the GET request is sent via the Angular $http() service.
In order to encode the left/right parenths, and the / char, I'm trying:
request.params.myData = request.params.myData.replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\//g, '%2F')
However, my server is still rejecting the request.
And I doing something wrong?

You're getting a Forbidden error. Sure you don't need to authenticate or pass a token?
Before getting too manual, I'd suggest trying JSON.stringify(obj) and as a second pass, encodeURIComponent(obj)
If you're posting a valid JSON object, you might want to consider POST instead of GET, if you have backend access.

Related

FastAPI rejecting POST request from javascript code but not from a 3rd party request application (insomnia)

When I use insomnia to send a post request I get a 200 code and everything works just fine, but when I send a fetch request through javascript, I get a 405 'method not allowed error', even though I've allowed post requests from the server side.
(Server side code uses python).
Server side code
from pydantic import BaseModel
from typing import Optional
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["POST", "GET"],
allow_headers=["*"],
)
class data_format(BaseModel):
comment_id : int
username : str
comment_body : Optional[str] = None
#app.post('/post/submit_post')
async def sumbit_post(somename_3: data_format):
comment_id = somename_3.comment_id
username = somename_3.username
comment_body = somename_3.comment_body
# add_table_data(comment_id, username, comment_body) //Unrelated code
return {
'Response': 'Submission received',
'Data' : somename_3
}
JS code
var payload = {
"comment_id" : 4,
"username" : "user4",
"comment_body": "comment_4"
};
fetch("/post/submit_post",
{
method: "POST",
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })
The error
What should I do to get around this error?
Thanks in advance.
To start with, your code seems to be working just fine. The only part that had to be changed during testing it (locally) was the URL in fetch from /post/submit_post to (for instance) http://127.0.0.1:8000/post/submit_post, but I am assuming you already changed that using the domain name pointing to your app.
The 405 Method Not Allowed status code is not related to CORS. If POST was not included in the allow_methods list, the response status code would be 400 Bad Request (you could try removing it from the list to test it). From the reference above:
The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response
status code indicates that the server knows the request method, but
the target resource doesn't support this method.
The server must generate an Allow header field in a 405 status code
response. The field must contain a list of methods that the target
resource currently supports.
Thus, the 405 status code indicates that the POST request has been received and recognised by the server, but the server has rejected that specific HTTP method for that particular endpoint. Therefore, I would suggest you make sure that the decorator of the endpoint in the version you are running is defined as #app.post, as well as there is no other endpoint with the same path using #app.get. Additionally, make sure there is no any unintentional redirect happening inside the endpoint, as that would be another possible cause of that response status code. For future reference, when redirecting from a POST to GET request, the response status code has to change to 303, as shown here. Also, you could try allowing all HTTP methods with the wildcard * (i.e., allow_methods=['*']) and see how that works (even though it shouldn't be related to that). Lastly, this could also be related to the configurations of the hosting service you are running the application; thus, might be good to have a look into that as well.
It's and old issue, described here. You need Access-Control-Request-Method: POST header in your request.

AngularJS $http.post() firing get request instead of post

i building an API service in angular and laravel, when i firing a GET call to the API everythings work fine, but when i fire POST call the service still use GET method instead of POST.
that is my service:
function LeadsAPI($http,$q,BASE_URL)
{
this.updateLead = function (lead_data) {
var url = BASE_URL+"/leads/update/";
var deferred = $q.defer();
$http.post(url , lead_data).then(function(response){
deferred.resolve(response.data);
});
return deferred.promise;
}
}
i call to this function from a Controller:
LeadsController.$inject = ['$scope', 'LeadsAPI'];
function LeadsController($scope , LeadsAPI)
{
LeadsAPI.updateLead({'lead_id' : res._id, 'the_lead': {'fist_name' : 'asd asd'}}).then(function (res) {
console.log(res);
});
}
i tried pass the parameters as a string ("a=b&c=d...") and added header :
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
in the run function at my App module instantiation but yet, i keep getting 405 (Method Not Allowed) error.
any ideas why and how to solve it? thank you very much all! :)
Seems the question is old and unanswered but google led me here. I hope someone will find this answer useful.
I had the same problem. $http was set to POST but server was returning error from GET request.
After checking the headers in a web inspector it shows the browser actually did two requests:
update/ 301 text/html angular.js:11442
update 405 xhr https://test.site/post/update
The first one is the one from $http and the second one is after a redirect.
As you can see the trailing slash URL is redirected to a non trailing one. With this redirect a POST request gets also changed to GET as well.
The solution is to change your request url to not contain trailing slashes:
url: BASE_URL+"/leads/update",
The GET works fine ... good
The POST returns 405 - Method not allowed
It sounds like it is doing a POST and the server you are posting to does not support POST requests to the endpoint in question
Can you please provide more information, such as the HTTP request and response headers when you make a GET request and the same for the POST request
You can access the header information via the NET tab in Firefox's Firebug or in Chrome console
Be sure that your API method is ready to handle a POST request. Maybe Angular is actually firing a POST request, but your method is expecting a GET.
If you are sure Angular is really firing a GET request instead of a POST for some reason, try to explicitly set the HTTP method on the $http object:
$http({
method: 'POST',
url: BASE_URL+"/leads/update/",
data: lead_data
}).then(function (response) {
deferred.resolve(response.data);
});

How do I send brackets "%5B" "%5D" as params on an Ajax Request using GET as method?

Using Ajax and the method GET, I am trying to send an url with brackets, but I am not getting the right encoding of them:
Request URL:http://myurl/search.html?_dc=1382510050331&search%5Bpostcode%5D=96231
instead of:
Request URL:http://myurl/search.html?_dc=1382510050331&search[postcode]=96231
Error:
Status Code:502 Host not found
Here is a snippet of my code:
Ext.Ajax.request({
url: 'http://myulr.lan/fpsearchjson.html',
method: 'GET',
params: {
"geosearch[postcode]":91111
},
success: function(response){
console.log("success");
},
failure: function(response){
console.log("failure");
}
});
Any help will be appreciated!
%5B and %5D are the url-encoded values of [ and ]. This should be encoded like it is in your example.
The problem seems to be that you are unable to reach the server. Try to reach the server in any way. Maybe open the URL in your favorite browser or telnet to it: telnet my.server.com 80
You need to convert your Get request though ajax should first convert to ASCII, same problem happen to me I solve it though convert my GET request into ASCII and again decode for use :)
You can use escape function to encode ,decode your url and parameter. On other side you can easily get that value in original format
for example
escape("It's me!") // result: It%27s%20me%21

Cross-domain Jquery JSONP POST to Rails app

This is killing me. Trying to load data from a different domain from an API-sorts of that I'm trying to write. When sending JSON parameters as POST they get discarded, I've read somewhere that some special headers must be set before_filter:
def cors_headers #set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Max-Age'] = "1728000"
headers['Access-Control-Allow-Headers'] = 'content-type, accept'
end
Haven't had any luck with these though. Guess it's a browser limitation.
When I try sending the data as GET instead of POST, it gets added to the URL like this:
Completed in 959ms (View: 0, DB: 2) | 200 OK [http://www.somedomain.com/connector/browse/Sport.json?callback=jQuery16105855946165975183_1379526705493&{%22filters%22:[{%22filter%22:{%22attribute%22:%22id%22,%22op
erator%22:%22%3E%22,%22value%22:%222%22}},{%22filter%22:{%22attribute%22:%22id%22,%22operator%22:%22%3C%22,%22value%22:%227523%22}}]}&_=1379526723982]
So Rails basically can't see the filters which are the params that I'm trying to send
Parameters: {"{\"filters\":"=>{}, "id"=>"Sport", "_"=>"1379526723982", "callback"=>"jQuery16105855946165975183_1379526705493"}
The jquery snippet I'm playing with is:
$jq.ajax({url: "http://www.somedomain.com/connector/browse/" + x + ".json" + "?callback=?",
type: "get", // tried post too
dataType: "json", // tried jsonp too
accepts: "json",
data: req_data, // this is JSON.stringified already
processData:false,
contentType: "application/json; charset=UTF-8;",
success: output
});
The sample data I'm trying to send is this
{"filters":[{"filter":{"attribute":"id","operator":">","value":"2"}},{"filter":{"attribute":"id","operator":"<","value":"7523"}}]}
Has anyone an idea on how to sort this out?
Muchos gracias!
Basically the JS SOP prevents us from sending a POST request and reading the response, but this can be worked around like this:
1) Compose the request data, send it as POST. Don’t expect to receive a response. Don’t use on success, use on complete instead. Add a random-ish variable to the request
2) Temporarily store the response on the server side in a file or session variable or memcached server, use the random var mentioned above as key within the store.
3) send a 2nd JSON AJAX call to fetch the cached object.
With memcached, make sure the cached responses get removed from time to time or expire, in my case the app gets a lot of traffic, it would spam my memcache servers with junk if not set to expire.
here's some sample code

How to send data in request body with a GET when using jQuery $.ajax()

The service API I am consuming has a given GET method that requires the data be sent in the body of the request.
The data required in the body is a list of id's separated by hypen and could potentially be very large and thus it must be sent in the body otherwise it will likely foobar somewhere in the browsers/proxies/webservers etc chain. Note I don't have control over the service or API so please don't make suggestions to change it.
I am using the following jQuery code however observing the request/response in fiddler I can see that the "data" I am sending is ALWAYS converted and appended to the query string despite me setting the "processData" option to false...
$.ajax({
url: "htttp://api.com/entity/list($body)",
type: "GET",
data: "id1-id2-id3",
contentType: "text/plain",
dataType: "json",
processData: false, // avoid the data being parsed to query string params
success: onSuccess,
error: onError
});
Anyone know how I can force the "data" value to be sent in the body of the request?
In general, that's not how systems use GET requests. So, it will be hard to get your libraries to play along. In fact, the spec says that "If the request method is a case-sensitive match for GET or HEAD act as if data is null." So, I think you are out of luck unless the browser you are using doesn't respect that part of the spec.
You can probably setup an endpoint on your own server for a POST ajax request, then redirect that in your server code to a GET request with a body.
If you aren't absolutely tied to GET requests with the body being the data, you have two options.
POST with data: This is probably what you want. If you are passing data along, that probably means you are modifying some model or performing some action on the server. These types of actions are typically done with POST requests.
GET with query string data: You can convert your data to query string parameters and pass them along to the server that way.
url: 'somesite.com/models/thing?ids=1,2,3'
we all know generally that for sending the data according to the http standards we generally use POST request.
But if you really want to use Get for sending the data in your scenario
I would suggest you to use the query-string or query-parameters.
1.GET use of Query string as.
{{url}}admin/recordings/some_id
here the some_id is mendatory parameter to send and can be used and req.params.some_id at server side.
2.GET use of query string as{{url}}admin/recordings?durationExact=34&isFavourite=true
here the durationExact ,isFavourite is optional strings to send and can be used and req.query.durationExact and req.query.isFavourite at server side.
3.GET Sending arrays
{{url}}admin/recordings/sessions/?os["Windows","Linux","Macintosh"]
and you can access those array values at server side like this
let osValues = JSON.parse(req.query.os);
if(osValues.length > 0)
{
for (let i=0; i<osValues.length; i++)
{
console.log(osValues[i])
//do whatever you want to do here
}
}
Just in case somebody ist still coming along this question:
There is a body query object in any request. You do not need to parse it yourself.
E.g. if you want to send an accessToken from a client with GET, you could do it like this:
const request = require('superagent');
request.get(`http://localhost:3000/download?accessToken=${accessToken}`).end((err, res) => {
if (err) throw new Error(err);
console.log(res);
});
The server request object then looks like {request: { ... query: { accessToken: abcfed } ... } }
You know, I have a not so standard way around this. I typically use nextjs. I like to make things restful if at all possible. If I need to make a get request I instead use post and in the body I add a submethod parameter which is GET. At which point my server side handles it. I know it's still a post method technically but this makes the intention clear and I don't need to add any query parameters. Then the get method handles a get request using the data provided in the post method. Hopefully this helps. It's a bit of a side step around proper protocol but it does mean there's no crazy work around and the code on the server side can handle it without any problems. The first thing present in the server side is if(subMethod === "GET"){|DO WHATEVER YOU NEED|}

Categories

Resources