What value actually need to provide {item-path} in view.delta OneDrive for Business API - onedrive

I am using /drive/root:/{item-path}:/view.delta for getting the changes of a file in OneDrive for Business in root folder. I have tried with the path like /drive/root:/Files/filename:/view.delta but the response is resource not found. Can someone please explain what exactly this value ?
The link I am following is below.
more details

The error would suggest that /Files/filename does not exist, however even if it did you'd run into another limitation of how view.delta currently works with OneDrive for Business. To make a long story short, it's limited to only working on the root of the drive, i.e. /drive/root/view.delta. Using this path you'll get back changes for ALL items within the drive, not just the one that you're interested in.
Given that you're trying to detect changes in a single file you may want to consider a standard metadata request with an If-None-Match header that contains the ETag of the last state your application saw.
For example, you'd first make a request without any additional headers to get the initial state:
Request:
GET /_api/v2.0/drive/root:/File/filename
Response:
200 OK
{
...
"name": "filename",
"etag": "\"aasdfasdf\"",
"modifiedDateTime": "2016-01-01T00:00:00Z",
...
}
At some point in the future you'd then make a call using the etag value in the If-None-Match header:
Request:
GET /_api/v2.0/drive/root:/File/filename
If-None-Match: "aasdfasdf"
Response:
304 Not Modified
If the file has actually changed you'd get back the new response.
Request:
GET /_api/v2.0/drive/root:/File/filename
If-None-Match: "aasdfasdf"
Response:
200 OK
{
...
"name": "filename",
"etag": "\"poihklhjl\"",
"modifiedDateTime": "2016-04-19T00:00:00Z",
...
}

Related

Office 365 REST API /$count filter giving wrong data

I'm trying to get count of records for different objects. The response of /$count filtered APIs is inconsistently giving wrong response.
I am referring this documentation link for usage instructions.
Request URL: GET https://outlook.office.com/api/v2.0/me/Events/$count
Response: -1
To verify if the above mentioned response is legitimate, I tried to get all events with a skip filter to identify the actual number of records present.
After a certain attempts following request URL gave me final count:
Request URL: GET https://outlook.office.com/api/v2.0/me/events/?$skip=159
Response:
{
"#odata.context": "https://outlook.office.com/api/v2.0/$metadata#Me/Events",
"value": [
{
"Id": "AAMkADMzYzIxNTBjLWUyMWUtNDgzYi04NTEwLTc5YTkzMWI5MmE4MgBGAAAAAABjOnbtK9ZkTIjwInd5bfYcBwDe_ScfFfAUQaKHRwnzV1lBAAAAAAENAADe_ScfFfAUQaKHRwnzV1lBAACs2ojfAAA=",
"CreatedDateTime": "2016-11-28T11:09:03.8359488Z",
"LastModifiedDateTime": "2017-02-21T08:04:48.8262751Z"
}
]
}
This implies that after skipping 159 records, I've 160th record present in the authenticated account but $count filtered API doesn't give me a valid response.
I tried testing this scenario with two different accounts where I noticed this anomaly for /message API as well. The HTTP GET call to messages/$count gives me 1563 whereas after trying with skip filter I found the total count to be 1396
I want to know if $count returns a legitimate response? If yes then explain this anomaly If no then is there any pattern where we should expect response to inconsistent?
To get a count of the number of events, you need to specify start time and end time. Here is what I use:
https://outlook.office.com/api/v2.0/me/calendarview/$count?startDateTime=2017-05-01T00:00:00Z&endDateTime=2017-05-31T23:59:59Z
If you don't specify the dates, you will get 400 with the following error message:
{"error":{"code":"ErrorInvalidParameter","message":"This request requires a time window specified by the query string parameters StartDateTime and EndDateTime."}}

Can PUT request change the URL?

My application with a HTTP API provides some resources that are identified by name. So, the URLs are constructed as the following:
/path/to/resources/<name>
For example:
/path/to/resources/my_resource
The resources can be updated with PUT operations. It is also allowed to rename a resource with such an update.
PUT /path/to/resources/my_resource
{"name": "new_name", <other properties>}
Response:
HTTP/1.1 204 No content
As a result, the updated resource is now accessible under a new URL:
GET /path/to/resources/new_name
Response:
HTTP/1.1 200 OK
{"name": "new_name", <other properties>}
The old URL is no longer valid:
GET /path/to/resources/my_resource
Response:
HTTP/1.1 404 Not found
Is such behavior correct? Should the PUT operation return the Location header with a new URL? Is it OK to return the Location header with the 204 No content status?
After writing this question I found another, quite similar: REST API Design : Is it ok to change the resource identifier during a PUT call?
The accepted answer was that it is allowed, but not recommended. Still don't know what about the Location header, though.
By changing a resource identifier, I understand you are deleting a resource and creating a new one. So, the approach you described in the question is basically a delete operation using the wrong HTTP verb.
According to the RFC 7231, the current reference for HTTP/1.1, PUT requests are used to create or replace a resource:
4.3.4. PUT
The PUT method requests that the state of the target resource be
created or replaced with the state defined by the representation
enclosed in the request message payload.
[...]
If the target resource does not have a current representation and the
PUT successfully creates one, then the origin server MUST inform the
user agent by sending a 201 (Created) response. If the target
resource does have a current representation and that representation
is successfully modified in accordance with the state of the enclosed
representation, then the origin server MUST send either a 200 (OK) or
a 204 (No Content) response to indicate successful completion of the
request.
[...]
I would do the following when the resource identifier needs to be changed:
Perform a DELETE in the existing resource. The response would be a 204 indicating the request was fulfilled.
Perform a POST or PUT to create the resource using the new identifier. The response would be a 201 indicating the resource was created. The response would contain a Location header indicating where the resource is located.
To replace the state of the target resource (keeping the resource identifier), perform a PUT and return a 204 to indicate the operation succeeded.
I don't know about your requirements, but I wouldn't allow the user to change or create the identifier of a resource. I would assume the resource identifier is immutable and should be generated by the application (UUID, of example) or an identifier generated by the database.
I agree with Cássio Mazzochi Molin's answer. However the question is theoretical one, whether renaming the resource really changes the 'identity' of a resource.
For example if a person's name changes, that does not change who the person is. I still would like the URI I previously got for the "same" person to work, even after the name change.
So I guess my point is not to include non-identity related information into the URI. Include an Id number or similar content-unrelated information.
Don't do a DELETE and PUT to another URI (don't relocate the resource) if the identity of the object did not change.

Onenote API (REST) - PATCH append - "must include a 'commands'" error when Commands is already supplied (?!)

Note: I'm pretty sure nothing's wrong with the PATCH query, I had it working before with 'Content-type':'application/json' and a constructed json file:
[
{
'target':'|TARGET_ID|',
'action':'append',
'content':'|HTML|'
}
]
For the purposes of this, the header supplied (authentication bearer is correct and will be omitted)
'Content-type':'multipart/form-data; Boundary=sectionboundary'
(note: Boundary=sectionboundary is in the same line)
Attempting to pass the following body as a PATCH to
https://www.onenote.com/api/v1.0/pages/|GUID|/content
returns a
"code":"20124","message":"A multi-part PATCH request must include a 'commands' part containing the PATCH action JSON structure." :
--sectionboundary
Content-Disposition: form-data; name="Commands"
Content-Type: application/json
[
{
'target':'|TARGET_ID|',
'action':'append',
'content':'|HTML|'
}
]
--sectionboundary
Content-Disposition: form-data; name="image-part-name"
Content-Type: image/png
|BINARY_IMAGE_DATA|
--sectionboundary--
As you can see, there's a Commands section already. Using smallcaps 'commands' doesn't help, and the correct syntax should be "Commands" as per the OneNote Dev Center documentation.
PS: |TARGET_ID| |HTML| |GUID| and |BINARY_DATA| are replaced with the correct content at runtime. Due to privacy constraints, the fact that you may use a different schema than I do, and how long |BINARY_IMAGE_DATA| actually is, I will not show the actual input unless required to solve the problem.
Would like to know if I missed anything - thanks in advance.
PPS: Yes, I realize i've omitted the img tag inside |HTML| somewhere. It shouldn't have anything to do with code 20124, and if I got it wrong should return another thing entirely.
Based on investigating the request information you shared, I can confirm that the PATCH request referenced as part of the correlation you provided does not match your posted header information.
The correlated PATCH request shows up as a multi-part request with only a single part that has Media Type "TEXT/HTML" and not "Application/JSON". Can you please check and confirm your request content ?
Let us continue to discuss this on email. If you still face issues calling the API, please write to me at machandw#microsoft.com
Regards,
Manoj

How do I use BigQuery patch?

In the BigQuery API documentation there is a method called patch. I am hoping that I can use it to alter the schema of an existing table. Unfortunately it is not supported by bq. But according to their website, you can try it at https://developers.google.com/bigquery/docs/reference/v2/tables/patch. However when I try it sends the following request:
PATCH https://www.googleapis.com/bigquery/v2/projects/(my project id)/datasets/tmp_bt/tables/change_cols?key={YOUR_API_KEY}
Content-Type: application/json
Authorization: Bearer (removed)
X-JavaScript-User-Agent: Google APIs Explorer
{
"schema": {
"fields": [
{
},
{
},
{
"mode": "nullable",
"name": "gotchahere",
"type": "string"
}
]
}
}
(I have no idea where the empty elements came from, and the editor is too painful to use to just paste in my existing table definition. I note that it is missing required elements like my project ID, which I expected to be included because they were required in the form) and then I get the response:
cache-control: private, max-age=0
content-encoding: gzip
content-length: 122
content-type: application/json; charset=UTF-8
date: Thu, 13 Jun 2013 22:22:09 GMT
expires: Thu, 13 Jun 2013 22:22:09 GMT
server: GSE
{
"error": {
"errors": [
{
"domain": "global",
"reason": "backendError",
"message": "Backend Error"
}
],
"code": 503,
"message": "Backend Error"
}
}
which is utterly useless. I've done a web search, and failed to find any examples of it in use.
Can anyone give me an example of using BigQuery patch to alter a table, and a description of what it can actually do?
TLDR: You need to supply the complete schema in the body of the patch request, not just the fields you're trying to add. The backend error is likely caused by the empty fields in that array.
BigQuery's API allows tables (and other resources) to be updated in two ways: update and patch.
The update method replaces the table resource with the new resource that you supply. This method is useful in cases where you want to take an existing table resource, modify it, and then post that modified table resource back to BigQuery in its entirety. (Note, however, that some fields of the object, such as creationTime, are considered immutable, so the new values supplied for these fields will be ignored.)
The patch method only replaces the fields that you include in the request, and leaves the rest of the resource unchanged. This method is useful if you want to make an isolated change to one field without worrying about the rest. This algorithm is applied recursively to any nested objects, but not to nested arrays. In other words, the patch resource that you send with the request is merged recursively with the existing resource until an array or scalar value is encountered, at which point the array or value in the patch object replaces the one in the existing resource.
Since the schema you're trying to update contains an array of fields, and since the patch method updates arrays wholesale, your patch object needs to contain the complete array of fields that you want in the resulting schema. (You can't add a field by specifying a one-field array in the patch object.)
Note that the table ID is given in the request URL, so it doesn't need to be included in the object itself.
Finally, the backend error is a problem on our end, likely a result of the two empty schema fields in your request. We'll dig further and hopefully improve the error message for the future.

can i use "http header" to check if a dynamic page has been changed

you can request the http header to check if a web page has been edited by looking at its date but how about dynamic pages such as - php, aspx- which grabs its data from a database?
Even though you might think it's outdated I've always found Simon Willison's article on Conditional GET to be more than useful. The example is in PHP but it is so simple that you can adapt it to other languages. Here it is the example:
function doConditionalGet($timestamp) {
// A PHP implementation of conditional get, see
// http://fishbowl.pastiche.org/archives/001132.html
$last_modified = substr(date('r', $timestamp), 0, -5).'GMT';
$etag = '"'.md5($last_modified).'"';
// Send the headers
header("Last-Modified: $last_modified");
header("ETag: $etag");
// See if the client has provided the required headers
$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
false;
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) :
false;
if (!$if_modified_since && !$if_none_match) {
return;
}
// At least one of the headers is there - check them
if ($if_none_match && $if_none_match != $etag) {
return; // etag is there but doesn't match
}
if ($if_modified_since && $if_modified_since != $last_modified) {
return; // if-modified-since is there but doesn't match
}
// Nothing has changed since their last request - serve a 304 and exit
header('HTTP/1.0 304 Not Modified');
exit;
}
With this you can use HTTP verbs GET or HEAD (I think it's also possible with the others, but I can't see the reason to use them). All you need to do is adding either If-Modified-Since or If-None-Match with the respective values of headers Last-Modified or ETag sent by a previous version of the page. As of HTTP version 1.1 it's recommended ETag over Last-Modified, but both will do the work.
This is a very simple example of how a conditional GET works. First we need to retrieve the page the usual way:
GET /some-page.html HTTP/1.1
Host: example.org
First response with conditional headers and contents:
200 OK
ETag: YourETagHere
Now the conditional get request:
GET /some-page.html HTTP/1.1
Host: example.org
If-None-Match: YourETagHere
And the response indicating you can use the cached version of the page, as only the headers are going to be delivered:
304 Not Modified
ETag: YourETagHere
With this the server notified you there was no modification to the page.
I can also recommend you another article about conditional GET: HTTP conditional GET for RSS hackers.
This is the exact purpose of the ETag header, but it has to be supported by your web framework or you need to take care that your application responds properly to requests with headers If-Match, If-Not-Match and If-Range (see HTTP Ch 3.11).
You can if it uses the http response headers correctly but it's often overlooked.
Otherwise storing a local md5-hash of the content might be useful to you (unless there's an easier in-content string you could hook out). It's not ideal (because it's quite a slow process) but it's an option.
Yes, you can and should use HTTP headers to mark pages as unexpired. If they are dynamic though (PHP, ASPX, etc.) and/or database driven, you'll need to manually control setting the Expires header/sending HTTP Not Modified appropriately. ASP.NET has some SqlDependency objects for this, but they still need to be configured and managed. (Not sure if PHP has something just like it, but there's probably something in PEAR if not...)
The Last-Modified header will only be of use to you if the programmer of the site has explicitly set it to be returned.
For a regular, static page Last-Modified is the timestamp of the last modification of the HTML file. For a dynamically generated page the server can't reliably assign a Last-Modified value as it has no real way of knowing how the content has changed depending on request, so many servers don't generate the header at all.
If you have control over the page, then ensuring the Last Modified header is being set will ensure a check on Last-Modified is successful. Otherwise you may have to fetch the page and either perform a regex to find a changed section (e.g. date/time in the header of a news site). If no such obvious marker exists, then I'd second Oli's suggestion of an MD5 on the page content as a way to be sure it has changed.