How to POST the contents of a file using curl - http

I'd like to be able to post the contents of a file to a MediaWiki site. So far I can do it as so:
curl --cookie wikiCookies.txt --negotiate -k -X POST -u:<username> -g 'https://<someWikiSite>/api.php?action=edit&title=TestPage&text=HelloWorld&token=<someToken>&format=json'
This works fine, but it has its limitations because of the length of the url.
Suppose I had a file foo.txt, how could I post the contents of this file to a MediaWiki site so that I wouldn't have to add the entire file contents to the url?
I've found the MediaWiki API http://www.mediawiki.org/wiki/API:Edit#Editing_pages, but I haven't been able to figure out how to curl POST entire file contents with it.
I think this should be a fairly simple question for anyone with a good understanding of curl, but no matter what I try, I can't get it to work.

Try this:
--data "text=<some_wiki_tag>this is encoded wiki content</some_wiki_tag>&title=TestPage&text=HelloWorld&token=<someToken>&format=json"

I think what you need is the -d, --data <data>
If the <data> starts with # then the rest should be a file name whose content will be send in the POST request.
Online curl manpage
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP server,
in the same way that a browser does when a user has filled in an HTML
form and presses the submit button. This will cause curl to pass the
data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F, --form.
-d, --data is the same as --data-ascii. To post data purely binary, you should instead use the --data-binary option. To URL-encode the
value of a form field you may use --data-urlencode.
If any of these options is used more than once on the same command
line, the data pieces specified will be merged together with a
separating &-symbol. Thus, using '-d name=daniel -d skill=lousy' would
generate a post chunk that looks like 'name=daniel&skill=lousy'.
If you start the data with the letter #, the rest should be a file
name to read the data from, or - if you want curl to read the data
from stdin. The contents of the file must already be URL-encoded.
Multiple files can also be specified. Posting data from a file named
'foobar' would thus be done with --data #foobar. When --data is told
to read from a file like that, carriage returns and newlines will be
stripped out.

Related

Why do I receive a UnsupportedMediaType message when trying to analyze a form?

I am using the forms recognizer preview. I have already trained a model using the documentation provided in this documentation.
https://learn.microsoft.com/en-us/azure/cognitive-services/form-recognizer/quickstarts/curl-train-extract
However when I attempt to execute the curl command to analyze the request; I get an error message indicating:
{"error":{"code":"UnsupportedMediaType","message":"In case of HTML form data, the multipart request must contain a document with a media type of - 'application/pdf', 'image/jpeg' or 'image/png'."}
The file I am uploading is a PDF (I've verified the response headers). I have also indicated this in the curl request as:
curl -X POST "https://[omitted]/formrecognizer/v1.0-preview/custom/models/[omitted]/analyze" -H "Content-Type: multipart/form-data" -F "form=[omitted];type=application/pdf" -H "Ocp-Apim-Subscription-Key: [omitted]"
Could you please share your PDF document, The issue may be with the PDF document containing different media types.
Just resolved it. Change the Content-Type to 'application/pdf' and in the body, send through the contents of the PDF, it doesn't seem to work with just the path.

Curl redirect without sending the first POST

I'm using "curl -L --post302 -request PUT --data-binary #file " to post a file to a redirected address. At the moment the redirection is not optional since it will allow for signed headers and a new destination. The GET version works well. The PUT version under a certain file size threshold works also. I need a way for the PUT to allow itself to be redirected without sending the file on the first request (to the redirectorURL) and then only send the file when the POST is redirected to a new URL. In other words, I don't want to transfer the same file twice. Is this possible? According to the RFC (https://www.rfc-editor.org/rfc/rfc2616#section-8.2) it appears that a server may send a 100 "with an undeclared wait for 100 (Continue) status, applies only to HTTP/1.1 requests without the client asking to send its payload" so what I'm asking for may be thwarted by the server. Is there a way around this with one curl call? If not, two curl calls?
Try curl -L -T file $URL as the more "proper" way to PUT that file. (Often repeated by me: -X and --request should be avoided if possible, they cause misery.)
curl will use "Expect: 100" by itself in this case, but you'll also probably learn that servers widely don't care about supporting that anyway so it'll most likely still end up having to PUT twice...

Does Firebase REST streaming support ordering and filtering child nodes?

I would like to stream changes to a Firebase location, but filter the results based on a query to some index, like so:
curl -i -L -H "Accept: text/event-stream" https://mydata.firebaseio.com/path.json?'orderBy="myIndexedField"&equalTo="desiredValue"'
What I observe is that Firebase appears to ignore my query and proceeds to stream all changes to that location whether they match the query or not. Is there any way to do this, other than writing code to perform my own client-side filtering?
EDIT
Frank's answer below shows that Firebase does indeed honor your query parameters. The problem I'm having still persists, and I simply misconstrued what was going on, as the situation turns out to be a little more complicated. I've reproduced my issue in Frank's Firebase, which he was kind enough to supply as a live example for this question.
Here are the steps to reproduce my issue:
Start a streaming query with the constraint type == 1:
$ curl -i -L -H "Accept: text/event-stream" 'https://stackoverflow.firebaseio.com/29265457/.json?print=pretty&orderBy="type"&equalTo=1'
In a separate terminal, post a new item with type==1:
$ curl -X POST -H "Content-Type: application/json" -d '{"type": 1}' https://stackoverflow.firebaseio.com/29265457/.json
{"name":"-JlY1nAmymCKw5lvLvMe"}
This object pops up in my ongoing curl stream as expected, since it matches the query of type==1:
event: patch
data: {"path":"/","data":{"-JlY1nAmymCKw5lvLvMe":{"type":1}}}
Now, here's the part I misinterpreted as Firebase ignoring queries. If I PUT that resource I just POSTed and change it to type==0, it still shows up in my stream! To perform the PUT:
$ curl -X PUT -H "Content-Type: application/json" -d '{"type": 0}' https://stackoverflow.firebaseio.com/29265457/-JlY1nAmymCKw5lvLvMe.json
And here's what I see pop up in my ongoing stream curl:
event: patch
data: {"path":"/","data":{"-JlY1nAmymCKw5lvLvMe":{"type":0}}}
If I PUT "type" to 0 again, it no longer shows up in my curl stream terminal. If I PUT type to 1, then it does pop up in my curl stream (expected). It's the transition from 1->0 where I get the unexpected event.
Also, using PATCH instead of PUT to modify "type" appears to result in the same behavior in the curl stream.
I think it's natural to expect that when I change a value to NOT match my query anymore, I wouldn't see it in my stream. However, it looks like perhaps the query is being matched before the value is edited, or something along those lines... I have no idea how this is implemented on the Firebase end.
So I guess the new question is: How can I avoid seeing changed values that don't match my query in the REST stream?
There are two things that could be wrong here:
you didn't define an index on myIndexedField
your URL is quoted incorrectly
Ad 1) When you access Firebase through the (JavaScript/iOS/Java) libraries, it will fall back to client-side ordering and filtering if you're ordering/filtering data that is not indexed. Given that the REST API doesn't come with a client-library, it cannot perform such a fallback and it will simply return the data unordered/unfiltered.
Ad 2) you need to put your single quotes around the entire URL, not just the query string. An example curl that works for me:
curl -i -L -H "Accept: text/event-stream" 'https://stackoverflow.firebaseio.com/29265457/.json?orderBy="type"&equalTo=0'
I push data to it with this JavaScript snippet:
new Firebase('https://stackoverflow.firebaseio.com/29265457/').push({ type: 0 });
And it shows up in the curl window; or it doesn't if I set type to 1.

REST API endpoint - weird path parameter

I am learning REST API and URI design and I have found one here:
https://raw.githubusercontent.com/JeanVEGA/MI-MPR-DIP-Admission/master/examples/requests.sh
I have a few questions.
There is for example:
User.resetPassword, anonymous by User's {email}
curl -i -X POST http://localhost:9090/admission/services/user/person/email:{email}/reset_password
I do not understand construction email:{email}... what does it mean? It means that if I have String path param, I need to do it in this way?
The similar is here:
Term.get
curl -i -H "Accept: application/json" -H "X-CTU-FIT-Admission-Session: [session identifier from User.identity]" http://localhost:9090/admission/services/term/dateOfTerm:{dateOfTerm}/room:{room}
room:{room} - Is this because room should be for example 123ABC? So it is not a number so it need to be written in this way?
And my last question:
User.resetPassword for User by Admission Code, send notification to User's Email and this {email}
curl -i -H "X-CTU-FIT-Admission-Session: [session identifier from User.identity]" -X POST http://localhost:9090/admission/services/user/admission/{admissionCode}/person/email:{email}/reset_password
My poiont of question is "reset_password" ... I thought due to right design principles that no verb should be in URI... because if the verb is in URI, I thought that it means that resource is actually an operation.
That url can be only a resource identifier. So this is an url template which waits a unique email address as a parameter. A filled in template should look something like this:
./person/email:my#email.adr/reset_password
note:
The reset_password is not a valid REST resource (it describes a service not a resource) and the POST method is mostly for resource creation (not for update or partial update). Real REST requests look like this:
PUT ./person/email:{email}/password "newpass"
PUT ./person/{id}/password "newpass"
PUT ./person/email:{email}/identification_factors/password "newpass"
PATCH ./person/email:{email}/identification_factors {password: "newpass"}
and so on...

How to test multipart/form-data POST request

I am trying to find a tool that will allow me to test a multipart/form-data POST request and tweak the request. Specifically, I want to test the absence/presence of the semi-colon in the content-type header:
multipart/form-data; boundary=140f0f40c9f411e19b230800200c9a66
We have a client that doesn't send a semi-colon and our new servlet (using Apache Commons FileUpload) can't parse the uploaded file. The old version of our servlet uses a different library method for accepting/parsing the request and it can parse the file. Until I can prove that the request will be successful by including the semi-colon, the owners of the client app don't want to make any changes to it.
I have been using cURL to run my tests against the servlet, but I can't tweak the request it generates to exclude the semi-colon. I have tried the Poster addon for Firefox and Fiddler to generate a test POST request, but they result in this error:
org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
Has anybody found a way to successfully test a multipart/form-data POST request with an uploaded file?
You can use curl for testing these libraries, here's an example using a multipart/form-data POST: https://stackoverflow.com/a/10765244/72176
One thing I like about a command-line tool like curl is it's easy to repeat (in bash, up & enter), and you can save the test for later.
Edit: It is definitely possible to send the custom header that you want to test. The key is to use curl's raw commands over the convenience methods which format the request for you. Use -H to pass in the raw header, and use --data-binary to pass in the body from a file without changing the line endings (very important for multipart/form-data which must have CRLF line endings). Here's an example:
curl -X POST -H "Content-Type: multipart/form-data; boundary=----------------------------4ebf00fbcf09" --data-binary #test.txt http://localhost:3000/test
of if it's more convenient not to use the intermediary file, you can write it one line like so:
curl -X POST -H "Content-Type: multipart/form-data; boundary=----------------------------4ebf00fbcf09" -d $'------------------------------4ebf00fbcf09\r\nContent-Disposition: form-data; name="example"\r\n\r\ntest\r\n------------------------------4ebf00fbcf09--\r\n' http://localhost:3000/test
These 2 examples include the semicolon, but you can remove it as needed.

Resources