I've been trying to perform an XML request. I've faced so many problems that I managed to solve. But this one I couldn't solve.
this is the script:
$url ="WebServiceUrl";
$xml="XmlRequest";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_MUTE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
It is giving me this error:
System.InvalidOperationException: Request format is invalid: text/xml. at System.Web.Services.Protocols.HttpServerProtocol.ReadParameters() at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
I'm still a noob at this. So go easy on me:)
thanks.
Looks like you're sending stuff as text/xml, which is not what it wants. Find the docs for this web service e.g. WSDL stuff if it's there, and find out what data formats it accepts.
Be sure e.g. that it's not really saying it will respond in XML, after receiving a request as standard HTML POST variables.
There are two main content types used with the HTTP POST method: application/x-www-form-urlencoded and multipart/form-data.
The content-type determines what the format of the CURLOPT_POSTFIELDS should be. If you are using the default, which is "application/x-www-form-urlencoded" you probably want to use build_http_query() to construct the url encoded query string.
If you are sending non-ASCII data you canpass an associative array with keys that match the field names and values that correspond to the value for the field. Using this technique will cause the request to be issued with a multipart/formdata content-type.
At this point, it sounds like your next step should be figuring out what fields the API is expecting.
application/x-www-form-urlencoded or multipart/form-data?
Related
I am trying to make a call from my Laravel application to the Bullhorn API to convert a document to HTML, but it looks like the file isn't being attached to the call. Below is my code:
$data = curl_file_create("full/path/to/file.docx", 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'testcv');
$ch = curl_init();
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
However I receive the following 500 error:
Bad File Uploaded: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is application/x-www-form-urlencoded
When I try to set the Content-Type explicitly:
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: multipart/form-data'
));
I still receive a 500 error, just slightly different:
Bad File Uploaded: the request was rejected because no multipart boundary was found
I don't believe it's an issue with the Bullhorn API because executing the following call through the command line works fine:
curl -X POST "https://restXXX.bullhornstaffing.com/rest-services/{corptoken}/resume/convertToHtml?format=docx&BhRestToken={bhRestToken}" -F "file=#full\path\to\file.docx"
I assume that for some reason the file isn't being attached in my PHP call but I cannot figure out why.
Any help would be greatly appreciated.
The content-type: multipart/form-data uses boundary parameter for encapsulation, you can pass the boundary value as a string
'Content-Type: multipart/form-data; boundary=---------------------------7da24f2e50046'
Boundary is a string of "--" followed by a random string.
https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
If I ever have any weird problems with requests, I always put the request into postman and test it there since it compiles most of the headers and options for you, then just hit the code button on the top right to generate code in whatever language you want.
For your case you could datadump (dd) out your $data variable and copy it into one of the postman fields then set the url as well as the request type then run it and see what you get back.
Just a suggestion on how to debug a problem like this, hope it helps! good luck!
So I am trying to retrieve only headers using cURL with the following:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
curl_setopt ($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
$output = curl_exec($ch);
The problem is that while trying to get headers of large file the script uses all the memory. I would like to avoid getting also the body and I have tried to use:
curl_setopt($ch, CURLOPT_NOBODY, true);
The problem is that this issues a HEAD request instead of GET. And some website retrun an error when you request with HEAD.
Is there any way with curl to retrieve only header without doing HEAD request?
First, don't use CURLOPT_RETURNTRANSFER as that's the option that makes it keep the entire response in memory.
Then, two options:
A) use a write callback and make that abort the transfer as soon as the first byte of the body is returned. There's a write callback example in the PHP.net docs.
B) use CURLOPT_RANGE and ask for only the first byte to be retrieved, 0-0. This avoids the write callback but has the downside that not all HTTP servers and URLs will acknowledge it.
If you dont have to use cURL, you could use get_headers(). By default get_headers uses a GET request to fetch the headers. And you could also modify that request by using stream_context_set_default()
$headers = get_headers('http://example.com');
More Info: PHP: get_headers
Here's the situation. On one side, we have a server, with a RESTful service. One possible query to it is a POST query to create an object. When that is done, the server returns a 'Location' header, to indicate where information on the newly created object can be found.
However, said server is anal about having the correct Content-Type for each request. For instance, POST requires 'application/json', and GET requires this to be unset (make sense, since GET doesn't have a body).
To sum up, we have:
www.example.com/articles/ ; one can send a POST request with 'Content-Type: application/json', and server will return 'Location: www.example.com/articles/123' if 123 is the id of the new object ;
www.example.com/articles/123 ; one can send a GET request with no 'Content-Type' and server will return a description of the new article object.
On client side, we use PHP with cURL. We use the CURLOPT_FOLLOWLOCATIONsetting so we can read the description of the newly created object. Obviously, we also set 'Content-Type: application/json' for our POST request:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"name": "test"}');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, "https://www.example.com/Articles/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$result=curl_exec($ch);
var_dump($result);
curl_close ($ch);
?>
This is what we get:
string(101) "{ "errorNo": 415, "error": "Unsupported Media Type Content-Type should not be set in a GET request" }"
I looked at the log of the server, and indeed, 'Content-Type: application/json' is sent to GET www.example.com/articles/123.
Is this an expected behaviour?
If yes, what is then best approach:
remove the 'Content-Type' check on GET requests, server-side?
(sounds silly)
forget about CURLOPT_FOLLOWLOCATION, and make 2 clearly separated curl requests, so I have control over the headers? (but then what's the point of CURLOPT_FOLLOWLOCATION?)
something else?
For control and testing, I also use Postman, and I have no problem with it, it follows the location, doesn't send the 'Content-Type' on the GET part (apparently) after the redirection and so I don't have an error.
EDIT:
There seems to be nothing useful in the PHP doc. But I found something interesting in the command line man page:
https://curl.haxx.se/docs/manpage.html
It says:
"WARNING: headers set with this option will be set in all requests - even after redirects are followed, like when told with -L, --location."
So I guess it probably is the expected behaviour for PHP too. May someone suggest best practices then?
Have you tried using
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
to set the post type
I'm new to XML, and usually use JSON to pass data. I am working with a new system, and this was part of their instructions to me about passing data:
The XML content then can be sent as either PAYLOAD on the stream or as an additional parameter. If the latter is done, the parameter name is RequestXML
I'm not sure what this means? I'm afraid if I pass it as a parameter, but I have a lot of text, it will make the URL too long, so I'd like to do the PAYLOAD option. I'm using PHP and Jquery to generate the array. I can create an XML file using PHP and have it properly formatted as XML, but sending it across is confusing me.
What do I need to do to get it sent as a PAYLOAD?
You'll likely just want to send a POST HTTP request. Here's an example using the curl library:
<?php
$url = "https://example.com/service";
$xml = "<foo />";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
?>
I have been given an example piece of code from a company I'm dealing with for how to post XML data to a URL then read the response. Unfortunately for me this in VBS which I don't have a good working knowledge of:
This is the section of code that I'm interested in. This should pass over the XML file that was read in to oXML then post it and read the response:
set oHTTP = CreateObject("Microsoft.XMLHTTP")
oHTTP.open "POST", "http://www.ophub.net/opxml/response.asp", false,00092,QW 'file url - with dealers Account number, Password
oHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
oHTTP.setRequestHeader "Content-Length", Len(sRequest)
oHTTP.send oXML
From what I understand of this in PHP this can be done with cUrl and I have come up with the following from bits that I have read online but this doesn't work and I'm not sure why.
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: application/x-www-form- urlencoded"));
curl_setopt($ch, CURLOPT_URL, "http://www.ophub.net/opxml/response.asp");
curl_setopt($ch, CURLOPT_USERPWD, "00092:QW");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "XML=" . $xml);
$content=curl_exec($ch);
echo $content;
I'm sure I can't be far off what I need but I can't seem to get there so any hep would be very much appreciated.
In your post fields just set the xml no need to set xml=
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
you also need return transfer true
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
It looks to me like that is precisely what you need. It seems to be an exact translation.
The only two potential issues that I can see are:
You PHP code seems to have a space in the middle of the Content-Type header value, this will most likely break things
You will, if you haven't already done so, need to URL encode the $xml data before sending it as part of a application/x-www-form-urlencoded message (clue's in the type name :-P), which you can do with urlencode().
It might be a good idea to build the body data as a string and echo it out, to ensure that the data is correct:
echo 'XML=' . urlencode($xml);
For the record wrapping XML messages in application/x-www-form-urlencoded is a horrible way to do things. But I've come across more than one API that does it, so I'm going to assume that your code is correct in this regard for the API you are trying to consume.