Onedrive uploading fails with the Internal Server Error - php

I'm trying to create file on the OneDrive using REST API with PHP, but in the response I retrieve HTTP status code 500.
Code:
`
$url = $this->buildUrl(
'{folder_id}/files/{filename}?access_token={token}',
array(
'folder_id' => $folderId,
'filename' => $filename,
'token' => $this->getAccessToken(),
)
);
$response = wp_remote_request($url, array(
'body' => $content,
'method' => 'PUT',
));
`
Error message from the response body:
An error occurred while performing the action. Try again later.
What i'm doing wrong?

I just went through the same problem. It worked for me when I removed 'Content-type' line from request header.
If you are using PHP Curl to send request in wp_remote_request, you can remove 'Content-type' line from request header by calling something similar to this, before calling curl_exec:
curl_setopt($ci, CURLOPT_HTTPHEADER, array("Content-Type:"));
By adding the code above, the actual request header looks like this (note there is no 'Content-Type'):
PUT /v5.0/{folderId}/files/{filename}?access_token={accesstoken}
User-Agent: SOMEAGENT
Host: apis.live.net
Accept: */*
Expect: 100-continue
Content-Length: 29
FYI: I got a hint from here:
http://msdn.microsoft.com/en-us/library/dn631834.aspx
"For a PUT request, leave the Content-Type blank and put the contents of the file in the request body."
Hope it helps.

Related

Fetch xml data from API response

Request:
$headers = array( 'Content-Type:application/xml' );
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://example.com',
CURLOPT_POST => 1,
CURLOPT_HEADER => $headers,
CURLOPT_USERPWD=>'test:test',
CURLOPT_POSTFIELDS => $XMLData
));
$APIResponse = curl_exec($curl);
curl_close($curl);
And I get this response from an API
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: ----
X-AspNet-Version: -----
X-Powered-By: ASP.NET
Date: ---- GMT
Content-Length: 100
<?xml version="1.0" encoding="utf-8"?><response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.com"><ID>12345</ID></response>
I want to fetch ID from xml ID tag. How can I get that in my php code?
You're getting the HTTP header data included within your response from cURL, which is making it hard to extract the XML part.
However this is happening due to a simple misunderstanding - the CURLOPT_HEADER option doesn't do what you think it does.
That doesn't include your request headers in the request (as your code seems to be trying to do), instead it sets an option telling cURL whether or not the response headers should be included in the main output or not. If you set
CURLOPT_HEADER => 0
in your code, your problem should go away - then only the response body (in your case, just the XML) will included in the output from curl_exec.
In the meantime, if you need to set custom HTTP headers in your request, you can do it via the CURLOPT_HTTPHEADER option - a detailed example can be found here and in many other places online.
P.S. Admittedly these option names are not, in themselves, very clear about the difference between them, but the PHP manual does describe what they do in more detail.

file_get_contents() gets 403 from api.github.com every time

I call myself an experienced PHP developer, but this is one drives me crazy. I'm trying to get release informations of a repository for displaying update-warnings, but I keep returning 403 errors. For simplifying it I used the most simple usage of GitHubs API: GET https://api.github.com/zen. It is kind of a hello world.
This works
directly in the browser
with a plain curl https://api.github.com/zen in a terminal
with a PHP-Github-API-Class like php-github-api
This works not
with a simple file_get_contents()from a PHP-Skript
This is my whole simplified code:
<?php
$content = file_get_contents("https://api.github.com/zen");
var_dump($content);
?>
The browser shows Warning: file_get_contents(https://api.github.com/zen): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden, the variable $content is a boolean and false.
I guess I'm missing some sort of http-header-fields, but neither can I find those informations in the API-Docs, nor uses my terminal curl-call any special header files and works.
This happens because GitHub requires you to send UserAgent header. It doesn't need to be anything specific. This will do:
$opts = [
'http' => [
'method' => 'GET',
'header' => [
'User-Agent: PHP'
]
]
];
$context = stream_context_create($opts);
$content = file_get_contents("https://api.github.com/zen", false, $context);
var_dump($content);
The output is:
string(35) "Approachable is better than simple."

file_get_contents Default headers

I was wondering what is the default Content-Type header option when requesting a json string from an API.
I've noticed even if the requested Content-Type is application/json the response header Content-Type will be text/html
Does file_get_contents set the headers automatically based on what it is requesting or does it have a default one that is used always?
Does file_get_contents set the headers automatically based on what it is requesting or does it have a default one that is used always?
I think no defaults. For the context parameter you read below and see the 4-th example in docs:
A valid context resource created with stream_context_create(). If you don't need to use a custom context, you can skip this parameter by NULL.
Tested with Wireshark.
PHP 5.5.8 sends:
POST /path HTTP/1.0
Host: example.com
Content-Length: [appropriate number]
Content-Type: application/x-www-form-urlencoded
For the following context:
$options = array(
'http' => array(
'method' => 'POST',
'content' => $content
)
);
$context = stream_context_create($options);

Guzzle 5.3: Unable to POST JSON body if larger than ~1MB

I'm using Guzzle 5.3 via Guzzle Services (via https://github.com/ticketevolution/ticketevolution-php) to attempt to POST to an API endpoint with a JSON body that includes a PDF encoded as base64. When the body is less than ~1MB it works fine. When the body is larger it seems that the body is never sent.
I have tested this with and without the Expect: 100 header and it does not seem to make a difference.
I have tested with Transfer-Encoding: chunked, but because the API needs the entire POST body in order to authenticate using chunked does not work.
We have tested with and without the load balance between the client and the appservers.
From everything we can tell the body just doesn't get sent when it is larger than ~1MB.
Does anyone have any ideas on how to get Guzzle 5.3 to send the body even when it is larger than 1MB?
Below is the log output
[2015-09-01 16:15:43] TEvoAPIClientLogger.CRITICAL:
>>>>>>>>
POST /v9/orders/2100732/deliver_etickets HTTP/1.1
Host: api.ticketevolution.com
User-Agent: ticketevolution-php/3.0.0dev Guzzle/5.3.0 curl/7.44.0 PHP/5.5.28
Content-Type: application/json
Content-Length: 1387036
X-Token: b47dsd8c0ab80a1e2bc24sc341415a2f
X-Signature: SwBOkdUOqG3SDtjVwi2etosdP+gppwuV5dCq8yMw9lM=
{"etickets":[{"item_id":1513651,"eticket":"JVBERi0xLjQKJeLjz9MKNCAwIG9iaiBbXQplb… [a whole lot of base64 snipped] …NwolJUVPRgo="}]}
<<<<<<<< --------
cURL error 52: Empty reply from server
Running into the same problem, a bit of debugging resulted in ending up at GuzzleHttp\Ring\Client\CurlFactory::applyBody(), and then this fixed the problem for me:
Setting a default configuration on the client
$client = new \GuzzleHttp\Client([
'defaults' => [
'config' => [
'curl' => [
'body_as_string' => true,
],
],
],
]);
Setting the configuration when issuing the request
$client->post('https://example.com', [
'json' => $json,
'config' => [
'curl' => [
'body_as_string' => true,
],
],
]);
Rewinding the previously fetched actual content stream
Since I'm fetching content from a remote server, this article by Matt Downling helped me in finding out that I need to rewind the actual stream before using it as a part of the multipart/form-data request:
$response->getBody()->seek(0);

Sending XML to URL in PHP (without cURL)

Trying to send the following XML data to URL below.
$xml="<?xml version='1.0' encoding='utf-8'?>
<Job>
<Name>Set-up - ".$client_name."</Name>
<Description></Description>
<ClientID>".$accountantid."</ClientID>
<StartDate>".$start_date."</StartDate>
<DueDate>".$due_date."</DueDate>
<TemplateID>".$templateid."</TemplateIDr>
</Job>";
$createjob_url="https:<url>apiKey=[apikey]&accountKey=[accountkey]";
$stream_options = array (
'http' => array (
'method' => "POST",
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'content' => $xml
)
);
$context=stream_context_create($stream_options);
$response=file_get_contents($createjob_url, false, $context);
echo "<p>".$response."</p>";
The response should come out 'OK', but its just blank.
The debug.log has the following error.
PHP Warning: file_get_contents(https:<url>?apiKey=[apikey]&accountKey=[accountkey]): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error
I noticed the URL changes the '&' to '&'. If I put the url directly into the browser, it doesnt work, however if I remove 'amp;' it gives me the OK response.
But then if I remove from the code 'false, $context' e.g. file_get_contents($createjob_url), the response comes back 'OK', so the URL is fine.
I am using Google App Engine hence unable to use cURL.
I assume it has something to do with my stream options? Any feedback would be greatly appreciated.
So looks like my issue was a couple of small things.
For the particular URL I was parsing to, I didnt need to have the XML tag, so removed <?xml version='1.0' encoding='utf-8'?>
They also wanted the content type as xml, so changed it to 'header' => "Content-type: text/xml"
Once I got these two sorted, all worked well :)

Categories