Server App on Heroku is not accessibe - ruby-on-rails

Hi we have a Ruby on Rails server application on Heroku, but when I send a post request to it, I always get a 400 Bad Request response. I have searched other 400 errors, but none are related to our issue. The HTTP response that we receive looks like this below:
HTTP/1.1 400 Bad Request
Server: Cowboy
Date: Fri, 14 Aug 2015 21:55:25 GMT
Content-Length: 0
The post request that I am sending looks like this below:
POST http://ourapp.herokuapp.com/api/v1/requests HTTP/1.0
Accept-Language: en-us
Accept: text/plain
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
Connection: Close
request=600&key=&newKey=danasecretkey&
Sorry, I had to put blank lines after each header or it would all show up on one line.
If I create an HTML form to send the data, there is no issue. It's when I then try to send the same request from our file server, that I get the errors. I tried using a preflight request with all of the correct request headings, but received the same 400 Bad Request error.
Does anyone have any suggestions as to what I might be doing wrong?

Well, just guessing from what you've said:
request=600&key=&newKey=danasecretkey&
It's likely that you have something like params.require(:key) in your controller. And your request is missing that parameter.
Rails will respond with 400 status in case you missed some require'd params.

What fixed it was switching from HTTP1.0 to HTTP1.1, adding the host header and changing the uri.
The logs didn't tell us anything, and the params were ok. The problem was not fully grasping the HTTP header requirements.

Related

Do browsers block POST requests if POST isn’t in the Access-Control-Allow-Methods value of the preflight OPTIONS response?

I think I understand CORS pretty well, but I'm still a bit puzzled about the browser's behavior when it comes to the preflight requests.
Let's say the browser issues this preflight request:
OPTIONS http://myserver.local:7000/api/order/4 HTTP/1.1
Host: myserver.local:7000
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-my-custom-header
Origin: http://localhost:5000
Sec-Fetch-Mode: cors
Referer: http://localhost:5000/
and my API returns:
HTTP/1.1 204 No Content
Date: Wed, 09 Mar 2022 12:52:50 GMT
Server: Kestrel
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT,DELETE
Access-Control-Allow-Origin: http://localhost:5000
Vary: Origin
Note that the server allows methods PUT and DELETE in the response to the preflight request, but not POST, which is the method of the actual CORS request.
Should the browser not block this request due to the mismatch between the actual request's method and the methods listed in the Access-Control-Allow-Methods header? Or is it enough that the server respond with a 20x status code for the browser to accept the preflight and then send the actual request?
My assumptions was that the browser would compare the allow-methods and block the request if the requested method did no match... Am I missing something?
TL;DR
No, the browser doesn't require the server to explicitly allow the POST method, because the latter, as a so-called CORS-safelisted method, gets a free pass.
More details
What the spec says
The answer, as always, lies in the Fetch standard (section 4.8), which specifies how CORS works:
Let methods be the result of extracting header list values given Access-Control-Allow-Methods and response’s header list.
And further down:
If request’s method is not in methods, request’s method is not a CORS-safelisted method, and request’s credentials mode is "include" or methods does not contain *, then return a network error.
(my emphasis)
What is a CORS-safelisted method? The term is defined in section 2.2.1:
A CORS-safelisted method is a method that is GET, HEAD, or POST.
Interpretation
If the method of the CORS request is one of GET, HEAD, or POST, the browser doesn't require the server to explicitly list that method in the Access-Control-Allow-Methods header for CORS preflight to succeed.
Experiment
I've found Jake Archibald's CORS playground useful for testing my (mis)understanding of CORS. Running this particular instance in your browser may convince you that the POST method doesn't need to be explicitly allowed for CORS preflight to succeed.

ASP.NET WebApi POST Status 405 message for unique signatures from Java app only?

I've got a weird problem in Microsoft.AspNet.WebApi{5.2.3}. The following two functions work fine alone, and they even work fine together, when my client is a .NET 4.6 HttpWebClient. However, as soon as a Java application tries to access the function, I get the following message:
HttpResponseProxy{HTTP/1.1 405 Method Not Allowed [Allow: GET,
Content-Length: 73, Content-Type: application/json; charset=utf-8,
Server: Microsoft-IIS/8.0, X-Powered-By: ASP.NET, Set-Cookie:
ARRAffinity=2cc8b96e3a4c1d6ee6a6e0;Path=/;Domain=mydomain.com, Date: Mon, 01
Feb 2016 13:44:57 GMT] ResponseEntityProxy{[Content-Type:
application/json; charset=utf-8,Content-Length: 73,Chunked: false]}}
It looks from the error message, that a GET is being tried (or expected?)?
I have added the explicit routing attribute as a last resort. I do not use it elsewhere.
Function 1:
[System.Web.Http.HttpPost]
[System.Web.Http.Route("api/Delegate/MigrateMix2User")]
public async Task<HttpResponseMessage> MigrateMix2User([FromBody] MigrateUserModel userInfo)
{...}
Function 2:
[System.Web.Http.HttpPost]
[System.Web.Http.Route("api/Delegate/ChangeUserEmail")]
public async Task<HttpResponseMessage> ChangeUserEmail([FromBody] ChangeEmailModel model)
{...}
Update Http Traces. Content doesn't look like a cause/problem?
Content usage traces: --- .NET 4.5 HttpClient, works fine:
POST http://localhost:1655/api/Delegate/MigrateMix2User HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsI...bE6s
Content-Type: application/json; charset=utf-8
Host: localhost:1655
Content-Length: 231
Expect: 100-continue
Connection: Keep-Alive
{"r_tc_app_client_id":"TN77PENKGu2Nq525c6Za93jbD7PiHzSo","r_email":"hyxx#acx.org","r_password":"dada","r_lang5":"en-EN","r_country2":"US","r_is_cto":"false","my_cto":"xzy","r_plan_id":"planet","addin_plan_id":"tst","addin_qty":2}
--- Java-Appache http Client: throws 405
"POST /api/Delegate/MirgrateMix2User HTTP/1.1[\r][\n]"
"Authorization: Bearer eyJhbGci...dIRiJE[\r][\n]"
"Content-Type: application/json[\r][\n]"
"Accept: application/json[\r][\n]"
"Content-Length: 274[\r][\n]"
"Host: mytargethost.com[\r][\n]"
"Connection: Keep-Alive[\r][\n]"
"User-Agent: Apache-HttpClient/4.3.6 (java 1.5)[\r][\n]"
"Accept-Encoding: gzip,deflate[\r][\n]"
"{"cto":"true","r_tc_app_client_id":"G04o5323zq1fo6hferi4axABdKvyiSCl","r_email":"kunsbe1#mailinator.com","r_password":"2Mh323aXp","r_lang5":"en-US","r_country2":"DE","r_is_cto":"true","r_plan_id":"05260000_LOR.2001","addin_plan_id":"05260000_LOR.2007","addin_qty":815}"
DEBUG [org.apache.http.wire] http-outgoing-2 << "HTTP/1.1 405 Method Not Allowed[\r][\n]"
2016-02-02 12:49:56,914 DEBUG Wire - http-outgoing-2 << "HTTP/1.1 405 Method Not Allowed[\r][\n]"
Based on the error message it's because you have marked your methods as HttpPost (verb POST) but your javascript is accessing these using GET (HttpGet).
You should include your java code if you want an exact fix in your calling code.
OK, the enigma is solved and I want to share the result. In the end, the solution was this post however, there is more to it: you see, the Java folks had a typo in there calling URL the whole time. However, they never noticed that it was the wrong function name since we were getting a 504 response status and not a 404. Also, when we commented out the second POST function in the WebApi Controller, it worked fine. And to make things more confusing, the error message said that the problem was due to a HttpGet being refused and the Java system was definitely sending a HttpPost. So here is what we learned: the WebApi Controller apparently lets any authorized POST call a single POST function, regardless of the name of the function. I suspect that the WebApi 2 default behavior is probably not intentional. Anyway, it led us off track since we assumed that the function name and URL were ok since the function was, after all, being executed. After making the changes in the link above, we started to get 404 instead of 504 and the source of the problem became evident... We didn't know whether to laugh or cry :-)

What does #_request.env['HTTP_X_MY_TOKEN'] return?

I'm not a ruby or rails programmer, but I'm tasked with reverse engineering an API for an RoR app. My HTTP POST requests are failing a validation check, where this line is supposed to provide a specific piece of data:
value = #_request.env['HTTP_X_MY_TOKEN'];
From what little experience I have and searching I've done, it appears to be looking for an HTTP request header MY_TOKEN but I'm unsure if that's the case.
My current HTTP request looks like this:
POST /myapp HTTP/1.1
Host: website.com:80
Content-Type: application/json
Content-Length: 12
my post data
If that is the case, can I simply add it to my HTTP post request headers as follows:
POST /myapp HTTP/1.1
Host: website.com:80
Content-Type: application/json
MY_TOKEN: sometokentext
Content-Length: 12
my post data
If not, how do I fill this value during my HTTP POST request?
Sending X-MY-TOKEN should do the trick.
As a side note, prepending custom headers with X- is no longer recommended and deprecated according to RFC-6648:
Custom HTTP headers : naming conventions

Adding News to D2L through valence

I'm hoping I can get some help with adding news the D2L. I've tried a lot and have gotten to the point where I don't know what else to try.
The error I keep on getting is 404. So, I'm thinking that either something is wrong with the URL I'm trying, or the data I'm sending (or maybe content type that is being sent).
I saw that when adding news, you need to pass it a multipart/mixed POST body. So, I've tried changing my code to include that, but I'm still not sure what is going on.
I don't think it's a permissions thing because I'm supposed to have full access with this account (and it's not 403, but 404)
This is the data I'm trying to send.
Overall Content Type:
ContentType: multipart/mixed;boundary=6da451c7
Data Being Sent:
--6da451c7
Content-Type: application/json
{"Title":"Test News Title","Body":{"Text":"Testing Testing 123...Testing Testing","Html":"<p>Testing Testing 123...Testing Testing</p>"},"StartDate":"2013-11-17T20:07:11Z","EndDate":"2013-12-02T20:07:11Z","IsGlobal":false,"IsPublished":false,"ShowOnlyInCourseOfferings":false}
--6da451c7
And here is the URL i'm trying to POST data to (slightly modified to not include personal data).
https://gsutest.desire2learn.com/d2l/api/le/1.3/6606/news/?x_a={{TOKEN}}&x_b={{TOKEN}}&x_c={{TOKEN}}&x_d={{TOKEN}}&x_t={{TIMESTAMP}}
I'm not sure where to go from here, any help would be nice. I realize I could be creating my POST body data wrong, but I'm just not sure what to try.
Thanks!
----Edit----
Ran a POST using fiddler and captured this data
POST https://gsutest.desire2learn.com/d2l/api/le/1.3/6606/news?x_a={{APPID}}&x_b={{USERID}}&x_c=OR0KIlHnHChrBvhHT99HVkH4WrD9dw_uPlpTGzKOdXc&x_d=b_TmyIHdTOL3U5bkNa1UNn11S4Yg7Cc3GOBoI911gLE&x_t={{TIMESTAMP}} HTTP/1.1
Content-Type: multipart/mixed;boundary=1649e26b
Host: gsutest.desire2learn.com
Content-Length: 342
Expect: 100-continue
Connection: Keep-Alive
--1649e26b
Content-Type: application/json
{"Title":"Test News Title","Body":{"Text":"Testing Testing 123...Testing Testing","Html":"<p>Testing Testing 123...Testing Testing</p>"},"StartDate":"2013-11-19T21:07:03.838Z","EndDate":"2013-12-04T21:07:01.413Z","IsGlobal":false,"IsPublished":false,"ShowOnlyInCourseOfferings":false}
--1649e26b
----Edit #2----
Ran another POST using fiddler and captured this data. The data that I'm sending came from: http://docs.valence.desire2learn.com/basic/fileupload.html#simple-uploads (under the upload to news section)
POST https://gsutest.desire2learn.com:443/d2l/api/le/1.3/6606/news/?x_a={{APP_ID}}&x_b={{USER_ID}}&x_c=rdzAFVUE6xBS24N5nE_4Hf5sbwpvJH1OVJaK4Ow-XT8&x_d=TmadrEGw55aKwS1uuNo68kvaR_pvYLUWJdsFa7LhrEQ&x_t={{TIMESTAMP}}" HTTP/1.1
Content-Type: multipart/mixed;boundary=xxBOUNDARYxx
Host: gsutest.desire2learn.com:443
Content-Length: 270
--xxBOUNDARYxx
Content-Type: application/json
{"EndDate": null, "IsPublished": false, "ShowOnlyInCourseOfferings": false,"Title": "Test title", "Body": {"Text": "Test body text", "HTML": null},"StartDate": "2013-02-20T13:15:30.067Z", "IsGlobal": false}
--xxBOUNDARYxx
I'm still getting "HTTP/1.1 404 Not Found" as the response headers.
Using the data you provided, I discovered that you are missing the millisecond value in your UTCDateTime format. By adding a millisecond value of .067 and .068 to each of the dates, I am able to POST successfully. I did this by using the Getting Started Sample against an LMS where I have an Instructor account with privileges to POST News items.

What's wrong with this OData batch update query?

I followed the example from here but I cannot get this to work!
I can't see anything wrong with the update query and I can't think of what to change because it seems fine. I'm only testing with one request because I wanted to make sure it works first.
Here's the request's body:
--batch_hJUuHcmH7ADWhYbtkF0o9JWlq
Content-Type: multipart/mixed; boundary=changeset_oYIVi6ByvAtKBlI7hqFWoOwX7
--changeset(oYIVi6ByvAtKBlI7hqFWoOwX7)
Content-Type: application/http
Content-Transfer-Encoding: binary
MERGE PrescriptionService.svc/Prescriptions(1L) HTTP/1.1
Host: 192.168.10.179
Content-Type: application/json;odata=verbose
{"PrescriptionType":"RegularMedicationPrescriptionType","Page":"0","Comment":"whoaaaaaa"}
--changeset(oYIVi6ByvAtKBlI7hqFWoOwX7)--
--batch(hJUuHcmH7ADWhYbtkF0o9JWlq)--
I get a 202 Accepted so the "overall" batch request is not malformed. This is the response from the server:
--batchresponse_d8e813eb-0327-4518-9312-9b7a55d0da0c
Content-Type: multipart/mixed; boundary=changesetresponse_fc085e3b-68a8-46dd-86c6-334b1070607d
--changesetresponse_fc085e3b-68a8-46dd-86c6-334b1070607d--
--batchresponse_d8e813eb-0327-4518-9312-9b7a55d0da0c--
I tried POSTing to that same URL in the batch body to create an entity and it doesn't work either, so it has to be something with the request body.
What's wrong with the request's body?
The changeset boundary as specified in the header:
boundary=changeset_oYIVi6ByvAtKBlI7hqFWoOwX7
must match exactly the one used later on:
--changeset(oYIVi6ByvAtKBlI7hqFWoOwX7)
Which it doesn't. I don't know why you added the parenthesis, but they should not be there.
Same goes for the batch boundary itself.

Resources