According to Vimeo API documentation:
The If-Modified-Since header enables you to return only those API resources that have been modified since a particular date and time.
The header looks like this:
If-Modified-Since: {ddd}, {D} {MMM} {YYYY} {HH}:{mm}:{ss} {Z}
NOTE: If your formatting codes are rusty, Tue, 20 Jun 2023 14:42:36 GMT is an example.
If none of the resources have been modified since this date, the API returns an empty response body and the HTTP status 304 Not Modified.
I'm using the Official PHP library for the Vimeo API.
According to GitHub issue #130, the PHP library's request() method accepts an array of headers. And this commit shows how the $headers array is passed and parsed:
public function request($url, $params = array(), $method = 'GET',
$json_body = true, array $headers = array())
// Set the headers
foreach ($headers as $key => $value) {
$curl_opts[CURLOPT_HTTPHEADER][] = sprintf('%s: %s', $key, $value);
}
But when I pass the future date shown in the example, I still receive a full list of videos rather than the "empty response body and the HTTP status 304 Not Modified" specified in the documentation.
What am I doing wrong?
$fields = array(
'created_time',
'modified_time'
);
$params = array(
'page' => $page,
'filter' => 'embeddable',
'filter_embeddable' => true,
'fields' => implode(',',$fields)
);
$headers = array(
'If-Modified-Since' => 'Tue, 20 Jun 2023 14:42:36 GMT'
);
$json_body = true;
$method = 'GET';
$response = $vimeo->request('/me/videos', $params, $method, $json_body, $headers);
Result:
Array
(
[0] => Array
(
[created_time] => 2018-06-05T19:27:18+00:00
[modified_time] => 2018-06-29T19:12:21+00:00
)
[1] => Array
(
[created_time] => 2016-06-02T03:01:40+00:00
[modified_time] => 2019-04-30T06:15:29+00:00
)
[2] => Array
(
[created_time] => 2016-05-29T05:31:46+00:00
[modified_time] => 2019-04-25T07:46:53+00:00
)
....
Edit
Based on this answer (not about Vimeo), it seems that the API might return the entire set of videos if even one of them was modified after the "If-Modified-Since" date.
If anything has changed in the entire response, then it will send the entire response to you.
But I'd still expect the result to be empty if the date is in the future. Am I misunderstanding?
Edit
Tom suggested that the Vimeo API ignores "If-Modified-Since" headers that are set in the future. I tried setting mine in the recent past, but I'm still getting results that were modified before that date:
$vimeo = new \Vimeo\Vimeo(false,false,$access_token);
$fields = array(
'modified_time'
);
$params = array(
'page' => 1,
'fields' => implode(',',$fields)
);
$method = 'GET';
$json_body = true;
$headers = array(
'If-Modified-Since' => 'Fri, 24 May 2019 14:42:36 GMT'
);
$response = $vimeo->request('/me/videos', $params, $method, $json_body, $headers);
echo"<pre>".print_r($response,true)."</pre>";
The result includes:
[21] => Array
(
[modified_time] => 2019-05-16T17:22:58+00:00
)
[22] => Array
(
[modified_time] => 2019-05-12T08:07:30+00:00
)
Edit
I was wrong. As mentioned above, I believe the entire response is returned if any item in the response has been modified since the "If-Modified-Since" timestamp. That made it look like the header wasn't working. But I set the timestamp as close as possible to the current time and I did get a "304 Not Modified" response, as Tom reported in his answer below. Others (content producers) also have access to the Vimeo account I'm testing against and I wasn't aware how recently they had modified content.
It's not documented by Vimeo, but I found out by experiment that:
When If-Modified-Since lies in the future, it is ignored.
Otherwise, the header works as expected. But take care of your timezones and possible clock-skew of a few seconds.
Vimeo's modification time is shown in the API response, in my case:
"modified_time": "2019-05-22T09:52:45+00:00",
If-Modified-Since: Wed, 22 May 2019 09:56:25 GMT returns a 304 Not Modified for my situation.
I've submitted a support request to Vimeo to clarify or change this behaviour.
Related
SOLUTION: I had malformed my JSON data for the payload body. The "ttl" => 30 was in the incorrect array() method. This probably won't help anyone in the future, moving the ttl key/value pair made this work correctly as seen below.
$data = array(
"statement" => array(
"actor" => array(
"mbox" => "mailto:test#example.com"
),
),
"ttl" => 30
);
I have checked numerous other StackOverflow questions and cannot find a solution that works. I should note that I am testing this using a local XAMPP server running on port 8080. Not sure if that matters. I have been able to get this working using Postman, but translating it to PHP has been problematic. Am I missing something? I am not all that familiar with PHP, but need this for work.
EDIT: Some more information about what the API is expecting. It's a fairly simple API that requires a JSON body, a Basic Authorization header, and a Content-Type: application/json.
Here is the JSON body I am using in Postman. This is a direct copy/paste from Postman, which is successfully communicating with the API:
{
"statement": {
"actor": {
"mbox": "mailto:test#example.com"
}
},
"ttl": 30
}
Is there a syntax error in my below PHP code for this? Again, I am learning PHP on the fly so I'm unsure if I am properly constructing a JSON payload using the array() method in PHP.
My code below has the $https_user,$https_password, and $url domain changed for obvious security reasons. In my actual PHP code, I have the same credentials and domain used in Postman.
The $randomSessionID serves no real purpose other than an identification number for future requests. Has no affect on the API response failing or succeeding.
<?php
$https_user = 'username';
$https_password = 'password';
$randomSessionID = floor((mt_rand() / mt_getrandmax()) * 10000000);
$url = 'https://www.example.com/session/' . $randomSessionID . '/launch';
$json = json_encode(array(
"statement" => array(
"actor" => array(
"mbox" => "mailto:test#example.com"
),"ttl" => 30
)
));
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: application/json\r\n'.
"Authorization: Basic ".base64_encode("$https_user:$https_password")."\r\n",
'content' => $json
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
?>
SOLUTION: I had malformed my JSON data for the payload body. The "ttl" => 30 was in the incorrect array() method. This probably won't help anyone in the future, but moving the ttl key/value pair made this work correctly as seen below.
$data = array(
"statement" => array(
"actor" => array(
"mbox" => "mailto:test#example.com"
),
),
"ttl" => 30
);
I made a code in PHP. The code works correctly when I run the command:
$payload = file_get_contents ('request.json');
However, I need to create dynamic content for the parameters passed by request.json
I made a routine that generates a string with exactly the same content as in the request.json file. However, when I pass this content to the $payload my function does not work.
$options = array (
'http' => array (
'header' => "Content-type: application / json",
'method' => 'POST',
'content' => $reqjson,
)
);
$context = stream_context_create ($options);
$result = file_get_contents ($url, false, $context);
Why is that? Isn't the type returned by the "file_get_contents" function a common string? How to fix it?
First, each line of header must end with "\r\n". Please append that to the "Content-Type" line. Second, if the function file_get_contents() returns false, it mean the request somehow failed. You should examine $http_response_header for more information:
$options = array(
'http' => array(
'header' => "Content-type: application/json\r\n",
'method' => 'POST',
'content' => $reqjson,
),
);
$context = stream_context_create($options);
if (($result = file_get_contents($url, false, $context)) === false) {
var_dump($http_response_header);
}
If the response header ($http_response_header) starts with HTTP/1.0 400 Bad Request, it means that the server somehow think your request is malformatted. Then,
If you have access to the requested server, try to find relevant log file(s) for more information.
If you have documentations to the requested server / service, please check carefully the accepted request format.
Often request format errors can be:
"appliation/json" is not an accepted request format; or
The content of $reqjson is malformat (e.g. it is supposed to be JSON text, not PHP array).
If you're using 3rd party service and still cannot figure out why it doesn't give you the expected result, seek help from the service provider.
Thanks, Koala Yeung.
As I said, the problem is that I tried to assemble in a string exactly the same content that is inside the request.json file. However, when I use the file_get_contents function to get the contents of the json file, it works. When it is directly in the string variable, the error occurs:
array (8) {[0] => string (24) "HTTP / 1.0 400 Bad Request" [1] => string (79) "x-cloud-trace-context: db4d34cce75495db89a04731bb718b49 / 1272894976542815412; o = 0" [2 ] => string (12) "vary: origin" [3] => string (45) "content-type: application / json; charset = utf-8" [4] => string (23) "cache-control: no-cache "[5] => string (19)" content-length: 229 "[6] => string (35)" Date: Tue, 08 Dec 2020 21:01:45 GMT "[7] => string (15) "Via: 1.1 google"}
bool (false)
I believe it is something related to this type of error:
"The content of $ reqjson is malformat (e.g. it is supposed to be JSON text, not PHP array)."
But the string is identical.
I am using official Vimeo PHP client.
I can upload a video, and set privacy.embed to whitelist.
Then doc tells me:
To add a domain to the whitelist, send a PUT request to /videos/{video_id}/privacy/domains/{domain}.
I tried
$privacy_uri = $uri . "/privacy/domains/testdomain.tld";
$domain_add_response = $client->request($privacy_uri);
where
- $uri is the /vimeo/<video_id>
- $client is born from new Vimeo(CLIENT_ID, CLIENT_SECRET, VIMEO_TOKEN);
Problem
Printing the $domain_add_response I get a 405 error, probably because of Allow (see the following response dump)
Array
(
[body] =>
[status] => 405
[headers] => Array
(
[Server] => nginx
[Content-Type] => application/json
[Allow] => PUT,DELETE,OPTIONS
[X-Vimeo-DC] => ge
[Accept-Ranges] => bytes
[Via] => 1.1 varnish
[Content-Length] => 0
[Date] => Mon, 15 Apr 2019 08:30:47 GMT
[Connection] => keep-alive
[X-Served-By] => cache-bwi5125-BWI, cache-mxp19820-MXP
[X-Cache] => MISS, MISS
[X-Cache-Hits] => 0, 0
[X-Timer] => S1555317047.232635,VS0,VE148
[Vary] => Accept-Encoding
)
)
I imagine I must set the PUT method in my request, but ... how ?
Solution found looking at api source code: https://github.com/vimeo/vimeo.php/blob/master/src/Vimeo/Vimeo.php#L88
where the signature of request is
public function request($url, $params = array(), $method = 'GET', $json_body = true, array $headers = array()): array
I understand that I can fix the problem, simply passing an empty $params array and specifing PUT as request $method
I changed this line
$domain_add_response = $client->request($privacy_uri);
Into this form
$domain_add_response = $client->request($privacy_uri, [], 'PUT');
And it works as expected
I'm trying to run a simple Web app over a ReactPHP Web server, but I can't figure out where to get POST data coming from an HTML form. The server is defined as:
include 'vendor/autoload.php';
register_shutdown_function(function() {
echo implode(PHP_EOL, error_get_last()), PHP_EOL;
});
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);
$http->on('request', function(React\Http\Request $request, React\Http\Response $response) {
print_r($request);
$response->writeHead(200, array('Content-type' => 'text/html'));
$response->end('<form method="POST"><input type="text" name="text"><input type="submit" name="submit" value="Submit"></form>');
});
$socket->listen(9000);
$loop->run();
When I post some string using the HTML form, the $request object, when printed on the console, looks like:
React\Http\Request Object
(
[readable:React\Http\Request:private] => 1
[method:React\Http\Request:private] => POST
[path:React\Http\Request:private] => /
[query:React\Http\Request:private] => Array
(
)
[httpVersion:React\Http\Request:private] => 1.1
[headers:React\Http\Request:private] => Array
(
[User-Agent] => Opera/9.80 (X11; Linux i686) Presto/2.12.388 Version/12.16
[Host] => localhost:9000
[Accept] => text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
[Accept-Language] => it,en;q=0.9
[Accept-Encoding] => gzip, deflate
[Referer] => http://localhost:9000/
[Connection] => Keep-Alive
[Content-Length] => 24
[Content-Type] => application/x-www-form-urlencoded
)
[listeners:protected] => Array
(
)
)
Here I can't find my data anywhere. I thought it should be located in the query property, but it's empty.
When I make GET requests, instead, data passed in the querystring can be found inside the query property of the $request object.
So, where can I find data passed with POST requests?
I repeat the last edit to my question here, so this question can be marked as answered.
Nevermind, found an answer here. Basically, it seems that React PHP does not support an easy way to read POST data yet. What we can do, though, is to read data as soon as it comes, watching the event data of the $request object:
$request->on('data', function($data) {
// Here $data contains our POST data.
// The $request needs to be manually ended, though.
});
I'm working with a wordpress plugin called Instagrabber: pluggin page. The plugin had been working perfectly for several months up until about a week ago when it started failing authentication while updating the image stream. At first, I thought the token expired, but after creating a few new testing accounts, the problem persisted.
I've isolated the problem to a couple lines of code in the main instagrabber-api.class.php file, pertaining to authenticating and retrieving the content:
$response = wp_remote_post( $request_uri, array(
'timeout'=> 10,
'method' => 'POST',
'body' => $data
)
);
$decoded_response = json_decode($response['body']);
This throws an 500 internal server error, and authentication fails. I've successfully authenticated using instagram's localhost setting, and connected with their API console, but when I make the request from our host, it fails.
This may not cover everything, so I'm happy to provide additional information, if needed.
** Edited **
Here are the values for $data and $response:
$data = Array (
'client_id' => $InstagramClientID,
'client_secret' => InstagramClientSecret,
'grant_type' => 'authorization_code',
'redirect_uri' => $InstagramRedirectURI,
'code' => $auth_code
)
If I print $data, everything appears fine, with all values pulling correctly.
$response is an array using wp_remote_post default return values, which can be found here for reference. The following is what we get returned:
Array (
[headers] =>
Array (
[cache-control] => no-cache
[content-type] => text/html
[date] => Mon, 07 Apr 2014 13:15:33 GMT
[server] => nginx
[content-length] => 87
[connection] => Close )
[body] =>
This seems to be where the 500 server error stems from. My thought is because of the Connection = Close, and empty body content.