Youtube API unexpected part on Update Message {0} - java

Been using the API for awhile now and have encountered a problem: A 400 Bad Request on "youtube.part" . Normally not a problem, I thought perhaps I have an inccorrect Part specified, the error message will tell me what is wrong and I can easily change it, however, the error is the following:
400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "youtube.part",
"location" : "part",
"locationType" : "parameter",
"message" : "{0}",
"reason" : "unexpectedPart"
} ],
"message" : "{0}"
}
Normally in the "message": "{0}" it should tell you what part is wrong. Having searched on here a bit, I can't seem to find a solution, right now I am only specifying snippet . In building my update request I am specifying only snippet.title snippet.tags[] & snippet.categoryId .
The above is used in a testing environment and the request is authorized with youtube scope, as I use it to upload the video just before to the same youtube channel.
My own Ideas are the it is perhaps:
Not possible to directly update a video, after loading it (however, it is possible to list)
That I have somehow encountered a bug
For those looking to recreate what I am getting, I took the following steps in my testing:
Set up a youtube instance using authorised credentials
Upload a random small file to the channel (setting video title etc.)
After a successful return attempt to list the video by id
Using this id, retrieve video resource from youtube
Alter the tags section, leaving the title etc unchanged
Attempt to update and receive that error
Any help would be appreciated and I really hope it isn't an obvious solution :)

This happens when your video update request doesn't list all the parts you are including in the video object you are sending. For example, if your video object has snippet and status (because you used video.setSnippet and video.setStatus), the first paremeter in the update method has to list both parts:
Video ve = listVids[0];
ve.setStatus(...)
ve.setSnippet(...)
...
YouTube.Videos.Update updateVideosRequest = youtube.videos().update("snippet, status", ve);
Video videoResponse = updateVideosRequest.execute();
Notice the first parameter of the youtube.videos().update, it has both status and snippet included.
Hope this can help you.

Related

Is there any statndard pattern for returning the JSON response [duplicate]

Do standards or best practices exist for structuring JSON responses from an API? Obviously, every application's data is different, so that much I'm not concerned with, but rather the "response boilerplate", if you will. An example of what I mean:
Successful request:
{
"success": true,
"payload": {
/* Application-specific data would go here. */
}
}
Failed request:
{
"success": false,
"payload": {
/* Application-specific data would go here. */
},
"error": {
"code": 123,
"message": "An error occurred!"
}
}
Yes there are a couple of standards (albeit some liberties on the definition of standard) that have emerged:
JSON API - JSON API covers creating and updating resources as well, not just responses.
JSend - Simple and probably what you are already doing.
OData JSON Protocol - Very complicated.
HAL - Like OData but aiming to be HATEOAS like.
There are also JSON API description formats:
Swagger
JSON Schema (used by swagger but you could use it stand alone)
WADL in JSON
RAML
HAL because HATEOAS in theory is self describing.
Google JSON guide
Success response return data
{
"data": {
"id": 1001,
"name": "Wing"
}
}
Error response return error
{
"error": {
"code": 404,
"message": "ID not found"
}
}
and if your client is JS, you can use if ("error" in response) {} to check if there is an error.
I guess a defacto standard has not really emerged (and may never).
But regardless, here is my take:
Successful request:
{
"status": "success",
"data": {
/* Application-specific data would go here. */
},
"message": null /* Or optional success message */
}
Failed request:
{
"status": "error",
"data": null, /* or optional error payload */
"message": "Error xyz has occurred"
}
Advantage: Same top-level elements in both success and error cases
Disadvantage: No error code, but if you want, you can either change the status to be a (success or failure) code, -or- you can add another top-level item named "code".
Assuming you question is about REST webservices design and more precisely concerning success/error.
I think there are 3 different types of design.
Use only HTTP Status code to indicate if there was an error and try to limit yourself to the standard ones (usually it should suffice).
Pros: It is a standard independent of your api.
Cons: Less information on what really happened.
Use HTTP Status + json body (even if it is an error). Define a uniform structure for errors (ex: code, message, reason, type, etc) and use it for errors, if it is a success then just return the expected json response.
Pros: Still standard as you use the existing HTTP status codes and you return a json describing the error (you provide more information on what happened).
Cons: The output json will vary depending if it is a error or success.
Forget the http status (ex: always status 200), always use json and add at the root of the response a boolean responseValid and a error object (code,message,etc) that will be populated if it is an error otherwise the other fields (success) are populated.
Pros: The client deals only with the body of the response that is a json string and ignores the status(?).
Cons: The less standard.
It's up to you to choose :)
Depending on the API I would choose 2 or 3 (I prefer 2 for json rest apis).
Another thing I have experienced in designing REST Api is the importance of documentation for each resource (url): the parameters, the body, the response, the headers etc + examples.
I would also recommend you to use jersey (jax-rs implementation) + genson (java/json databinding library).
You only have to drop genson + jersey in your classpath and json is automatically supported.
EDIT:
Solution 2 is the hardest to implement but the advantage is that you can nicely handle exceptions and not only business errors, initial effort is more important but you win on the long term.
Solution 3 is the easy to implement on both, server side and client but it's not so nice as you will have to encapsulate the objects you want to return in a response object containing also the responseValid + error.
The RFC 7807: Problem Details for HTTP APIs is at the moment the closest thing we have to an official standard.
Following is the json format instagram is using
{
"meta": {
"error_type": "OAuthException",
"code": 400,
"error_message": "..."
}
"data": {
...
},
"pagination": {
"next_url": "...",
"next_max_id": "13872296"
}
}
I will not be as arrogant to claim that this is a standard so I will use the "I prefer" form.
I prefer terse response (when requesting a list of /articles I want a JSON array of articles).
In my designs I use HTTP for status report, a 200 returns just the payload.
400 returns a message of what was wrong with request:
{"message" : "Missing parameter: 'param'"}
Return 404 if the model/controler/URI doesn't exist
If there was error with processing on my side, I return 501 with a message:
{"message" : "Could not connect to data store."}
From what I've seen quite a few REST-ish frameworks tend to be along these lines.
Rationale:
JSON is supposed to be a payload format, it's not a session protocol. The whole idea of verbose session-ish payloads comes from the XML/SOAP world and various misguided choices that created those bloated designs. After we realized all of it was a massive headache, the whole point of REST/JSON was to KISS it, and adhere to HTTP. I don't think that there is anything remotely standard in either JSend and especially not with the more verbose among them. XHR will react to HTTP response, if you use jQuery for your AJAX (like most do) you can use try/catch and done()/fail() callbacks to capture errors. I can't see how encapsulating status reports in JSON is any more useful than that.
For what it's worth I do this differently. A successful call just has the JSON objects. I don't need a higher level JSON object that contains a success field indicating true and a payload field that has the JSON object. I just return the appropriate JSON object with a 200 or whatever is appropriate in the 200 range for the HTTP status in the header.
However, if there is an error (something in the 400 family) I return a well-formed JSON error object. For example, if the client is POSTing a User with an email address and phone number and one of these is malformed (i.e. I cannot insert it into my underlying database) I will return something like this:
{
"description" : "Validation Failed"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Invalid phone number."
} ],
}
Important bits here are that the "field" property must match the JSON field exactly that could not be validated. This allows clients to know exactly what went wrong with their request. Also, "message" is in the locale of the request. If both the "emailAddress" and "phoneNumber" were invalid then the "errors" array would contain entries for both. A 409 (Conflict) JSON response body might look like this:
{
"description" : "Already Exists"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Phone number already exists for another user."
} ],
}
With the HTTP status code and this JSON the client has all they need to respond to errors in a deterministic way and it does not create a new error standard that tries to complete replace HTTP status codes. Note, these only happen for the range of 400 errors. For anything in the 200 range I can just return whatever is appropriate. For me it is often a HAL-like JSON object but that doesn't really matter here.
The one thing I thought about adding was a numeric error code either in the the "errors" array entries or the root of the JSON object itself. But so far we haven't needed it.
Their is no agreement on the rest api response formats of big software giants - Google, Facebook, Twitter, Amazon and others, though many links have been provided in the answers above, where some people have tried to standardize the response format.
As needs of the API's can differ it is very difficult to get everyone on board and agree to some format. If you have millions of users using your API, why would you change your response format?
Following is my take on the response format inspired by Google, Twitter, Amazon and some posts on internet:
https://github.com/adnan-kamili/rest-api-response-format
Swagger file:
https://github.com/adnan-kamili/swagger-sample-template
The point of JSON is that it is completely dynamic and flexible. Bend it to whatever whim you would like, because it's just a set of serialized JavaScript objects and arrays, rooted in a single node.
What the type of the rootnode is is up to you, what it contains is up to you, whether you send metadata along with the response is up to you, whether you set the mime-type to application/json or leave it as text/plain is up to you (as long as you know how to handle the edge cases).
Build a lightweight schema that you like.
Personally, I've found that analytics-tracking and mp3/ogg serving and image-gallery serving and text-messaging and network-packets for online gaming, and blog-posts and blog-comments all have very different requirements in terms of what is sent and what is received and how they should be consumed.
So the last thing I'd want, when doing all of that, is to try to make each one conform to the same boilerplate standard, which is based on XML2.0 or somesuch.
That said, there's a lot to be said for using schemas which make sense to you and are well thought out.
Just read some API responses, note what you like, criticize what you don't, write those criticisms down and understand why they rub you the wrong way, and then think about how to apply what you learned to what you need.
JSON-RPC 2.0 defines a standard request and response format, and is a breath of fresh air after working with REST APIs.
The basic framework suggested looks fine, but the error object as defined is too limited. One often cannot use a single value to express the problem, and instead a chain of problems and causes is needed.
I did a little research and found that the most common format for returning error (exceptions) is a structure of this form:
{
"success": false,
"error": {
"code": "400",
"message": "main error message here",
"target": "approx what the error came from",
"details": [
{
"code": "23-098a",
"message": "Disk drive has frozen up again. It needs to be replaced",
"target": "not sure what the target is"
}
],
"innererror": {
"trace": [ ... ],
"context": [ ... ]
}
}
}
This is the format proposed by the OASIS data standard OASIS OData and seems to be the most standard option out there, however there does not seem to be high adoption rates of any standard at this point. This format is consistent with the JSON-RPC specification.
You can find the complete open source library that implements this at: Mendocino JSON Utilities. This library supports the JSON Objects as well as the exceptions.
The details are discussed in my blog post on Error Handling in JSON REST API
For those coming later, in addition to the accepted answer that includes HAL, JSend, and JSON API, I would add a few other specifications worth looking into:
JSON-LD, which is a W3C Recommendation and specifies how to build interoperable Web Services in JSON
Ion Hypermedia Type for REST, which claims itself as a "a simple and intuitive JSON-based hypermedia type for REST"
There is no lawbreaking or outlaw standard other than common sense. If we abstract this like two people talking, the standard is the best way they can accurately understand each other in minimum words in minimum time. In our case, 'minimum words' is optimizing bandwidth for transport efficiency and 'accurately understand' is the structure for parser efficiency; which ultimately ends up with the less the data, and the common the structure; so that it can go through a pin hole and can be parsed through a common scope (at least initially).
Almost in every cases suggested, I see separate responses for 'Success' and 'Error' scenario, which is kind of ambiguity to me. If responses are different in these two cases, then why do we really need to put a 'Success' flag there? Is it not obvious that the absence of 'Error' is a 'Success'? Is it possible to have a response where 'Success' is TRUE with an 'Error' set? Or the way, 'Success' is FALSE with no 'Error' set? Just one flag is not enough? I would prefer to have the 'Error' flag only, because I believe there will be less 'Error' than 'Success'.
Also, should we really make the 'Error' a flag? What about if I want to respond with multiple validation errors? So, I find it more efficient to have an 'Error' node with each error as child to that node; where an empty (counts to zero) 'Error' node would denote a 'Success'.
I used to follow this standard, was pretty good, easy, and clean on the client layer.
Normally, the HTTP status 200, so that's a standard check which I use at the top. and I normally use the following JSON
I also use a template for the API's
dynamic response;
try {
// query and what not.
response.payload = new {
data = new {
pagination = new Pagination(),
customer = new Customer(),
notifications = 5
}
}
// again something here if we get here success has to be true
// I follow an exit first strategy, instead of building a pyramid
// of doom.
response.success = true;
}
catch(Exception exception){
response.success = false;
response.message = exception.GetStackTrace();
_logger.Fatal(exception, this.GetFacadeName())
}
return response;
{
"success": boolean,
"message": "some message",
"payload": {
"data" : []
"message": ""
... // put whatever you want to here.
}
}
on the client layer I would use the following:
if(response.code != 200) {
// woops something went wrong.
return;
}
if(!response.success){
console.debug ( response.message );
return;
}
// if we are here then success has to be true.
if(response.payload) {
....
}
notice how I break early avoiding the pyramid of doom.
I use this structure for REST APIs:
{
"success": false,
"response": {
"data": [],
"pagination": {}
},
"errors": [
{
"code": 500,
"message": "server 500 Error"
}
]
}
A bit late but here is my take on HTTP error responses, I send the code, (via status), the generic message, and details (if I want to provide details for a specific endpoint, some are self explanatory so no need for details but it can be custom message or even a full stack trace depending on use case). For success it's a similar format, code, message and any data in the data property.
ExpressJS response examples:
// Error
res
.status(422)
.json({
error: {
message: 'missing parameters',
details: `missing ${missingParam}`,
}
});
// or
res
.status(422)
.json({
error: {
message: 'missing parameters',
details: 'expected: {prop1, prop2, prop3',
}
});
// Success
res
.status(200)
.json({
message: 'password updated',
data: {member: { username }}, // [] ...
});
Best Response for web apis that can easily understand by mobile developers.
This is for "Success" Response
{
"code":"1",
"msg":"Successfull Transaction",
"value":"",
"data":{
"EmployeeName":"Admin",
"EmployeeID":1
}
}
This is for "Error" Response
{
"code": "4",
"msg": "Invalid Username and Password",
"value": "",
"data": {}
}

Google Play Developer API - 400 Invalid Value - InAppPurchases

My question is similar to this one. However, I am using the API Java Client Library with a service account, making calls to the API from my server.
My code is following this guide, which is very simple. However, I can't seem to get an appropriate error for my request. This is how I build my AndroidPublisher:
val credential = GoogleCredential.fromStream(FileInputStream(
"/path/to/json"
)).createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER))
androidPublisher = AndroidPublisher.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(packageName)
.build()
Where the JSON is generated from the Developer Console, under Service Accounts. This is how I make my request:
androidPublisher.purchases().subscriptions().get(packageName, "valid-sku", "invalid-token").execute()
My subscription ID is valid but my token is invalid. I expect an error such as "invalid token" in the response. However, what I get is:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid Value",
"reason" : "invalid"
} ],
"message" : "Invalid Value"
}
Is that a generic error because of the invalid token or is it an authentication issue? If it an authentication issue, how do I solve it? If it is an invalid token issue, how am I supposed to know?
Some more information:
I get the same error when trying to make that call from the API Explorer as well (this time using a Client ID and API Key instead of Service Account).
I have not delegated domain-wide access to the service account. Do I have to for some reason?
I can successfully make other calls to the API such as inappproducts.list
From my experiences, if you have HTTP 400 error with Invalid Value then that purchase or subscription is FRAUD.
You can check out Order Id part of those purchases. Probably in the format of XXXXXXXXXXXX.XXXXXXXXXXXX which is wrong and should be GPA.XXXX.XXXXX.XXXXX.XXX
I don't really count the X char number. I just added to show the logic.
In my case the problem was that I was calling:
purchases.products.get
Instead of:
purchases.subscriptions.get
So, the reason that happened was just because the purchaseToken I was using was wrong.
I did not expect that to be the reason as I thought that in the case of an invalid token, I would receive a "token invalid" error (or something similar). As it turns out, the responses given by Google are pretty inconsistent (a 404 could also be given for an invalid token).
Scratched my head for a few hours, ALL my parameters were correct, and then well.. I realized that I was barking up the wrong tree (endpoint)
https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}
is not this
https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}
/purchases/subscriptions/.. vs /purchases/products/..
For all those who run into this problem, 99% of you need to publish the application for internal testers.
Follow this guide: https://support.google.com/googleplay/android-developer/answer/6062777?hl=en

PACT : How to have dynamic path with valid data that is present in Provider DataBase

I have a restFul API http://localhost:8080/books/{id} which return a book with a particular ID.
ex:
GET http://localhost:8080/books/1
will return
{
"id" : 1,
"pages" : 20,
"price" : 100
}
GET http://localhost:8080/books/2
will return
{
"id" : 2,
"pages" : 30,
"price" : 120
}
I have written my consumer expectations using regex in place of {id} and have generated the PACT.
There is no data present in the provider now. (no book information in present in the database). When I run pact verfication on provider side it fails since it is not able to get any information by hitting the actual service to cross check the contract.
Can the contract be verified without data being present in the provider database? or is there any workaround for the same?
Also the DB of provider can change if we deploying the provider into multiple environments, how to handle this?
Appreciate the help. Thanks.
Why would you want to workaround that? The point of contract testing is so that you can verify that both sides of the contract are properly met!
You might want to look at Provider States [1] for this.
Which language are you using?
The article provided gives you some background. In JVM, you can look at the #State annotation https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-provider-junit#example-of-http-test.
In your consumer, you would specify a state such as "Given a book with ID 1 exists". On the provider side, the framework will invoke the #State annotation corresponding to this expectation. This gives you the opportunity to ensure any state data exists (in this case, that book) before the test case runs.
[1] https://docs.pact.io/documentation/provider_states.html
First of all, none of the above URL works. & its so freaking difficult to use this framework.. none of the API has proper documentation and also bloody when some thing does not work, it does not give proper error message also.
In my case, I have been trying to send a Request Parameter called "business-date" which expects a date with format "yyyy-MM-dd" and none of the below options seems to be working --
matchQuery("business-date", "\\d{4}-\\d{2}-\\d{2}", "2020-05-18")
query("business-date="+getBusinessDate())
queryMatchingDate("business-date", "yyyy-MM-dd")
matchQuery("business-date", "\\d{4}-\\d{2}-\\d{2}")
queryMatchingDate("business-date", "yyyy-MM-dd")
queryMatchingISODate("business-date", "yyyy-MM-dd")
The exception looks like this
org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 Internal Server Error: [{ "error": "Unexpected request : \tmethod: GET\n\tpath: \/api\/batch_activities\/ACTIVITY\/STARTED\n\tquery: {}\n\theaders: {X-b3-traceid=[6c88f0a1a0ae288e], Accept=[application\/json], Connection=[ke... (443 bytes)]
Caused by: org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 Internal Server Error: [{ "error": "Unexpected request : \tmethod: GET\n\tpath: \/api\/batch_activities\/ACTIVITY\/STARTED\n\tquery: {}\n\theaders: {X-b3-traceid=[6c88f0a1a0ae288e], Accept=[application\/json], Connection=[ke... (443 bytes)]
Once instance of the DSL looks like below -
builder.given("Fetch Batch Activity by status")
.uponReceiving("Receiving Batch activity status").headers(headers).method(HttpMethod.GET)
.matchPath(pathRegex, path)
.matchQuery("business-date", "\\d{4}-\\d{2}-\\d{2}")
.willRespondWith().status(200).headers(headers).body(jsonUtil.getObjectAsString(
formatBatchActivityForStatus(FeedExporterConstants.BATCH_STATUS_STARTED)))
.toPact();

using the facebook API to receive the page ID by a post ID

I have an issue that I only have the post IDs of posts in my data repository. Since the Graph API I have to prefix the page ID before the post ID. Since I have no information what page posted this post I have a problem here.
I have my post IDs available but now need to know which post is allowed to get which post ID as prefix.
Therefore I'm looking for a way to give a post ID and receive the page ID.
Any API call that might give me that information actively or just a side-information?
I found this here:
https://graph.facebook.com/v2.8/139946919369293_811518108920728?access_token={token}&fields=from
?fields=from
does return this:
{
"from": {
"name": "Henkel Careers",
"id": "301655703240307"
},
"id": "301655703240307_811518108920728"
}
Unfortunetly that does not make any sense especially in my case. Since the Graph API does ONLY allow {page_id}_{post_id} combinations you need to actually provide the page_id in order to receive the page id by the mentioned above request.
I hope somebody has another solution!
You can try using a users access_token to get a set of page_access_tokens - then you can try mapping to the data repository and give them the option of posting to these pages using these access tokens based on the return JSON object data.

Google Drive service account returns 403 usageLimits

I'm trying to write an AppEngine app that writes a Google Document to Google Drive, puts in a specific set of folders and sets access rights. I have this working with the old DocsList API but since that just got deprecated I decided to update my code (and I had some additional functions to add anyway).
Problem I'm facing is this: When I use a service account and try to impersonate a specific user I get a 403 with usageLimits even though I have not used up any of my quota.
Here is the code I'm using:
GoogleCredential credentials = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("xxxxxxxxxxgserviceaccount.com")
.setServiceAccountScopes(DriveScopes.DRIVE)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File("xxxx-privatekey.p12"))
.setServiceAccountUser("user#xxxxxx.org").build();
I than use these credentials to initiate my Drive object:
Drive d = Drive.builder(httpTransport, jsonFactory)
.setHttpRequestInitializer(credentials)
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
#Override
public void initialize(JsonHttpRequest request) {
DriveRequest driveRequest = (DriveRequest) request;
driveRequest.setPrettyPrint(true);
}
}).setApplicationName("MYAPPNAME").build();
BTW: I've tried using new Drive(....) but that just won't work, no matter what I try. Keeps throwing errors that internal methods are not found!
Back to this issue:
When I than use 'd' to call something like .files().get("SOMEFILEID").execute() I get a 403
{ "code" : 403,
"errors" : [ {
"domain" : "usageLimits",
"message" : "Daily Limit Exceeded. Please sign up",
"reason" : "dailyLimitExceededUnreg",
"extendedHelp" : "https://code.google.com/apis/console"
} ],
"message" : "Daily Limit Exceeded. Please sign up"
}
I can't figure out why this doesn't work. I've look online all day but can't find a suitable answer. Some help is very much appreciated.
So pinoyyid's answer did help, although it wasn't the definitive answer.
I ended up solving it like this:
I took my AppID (xxxxx.apps.googleusercontent.com) and added it to my CPanel https://www.google.com/a/cpanel/[[YOURDOMAIN]]/ManageOauthClients
with these scopes:
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/drive.file
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile
After that I had could do an authenticated request to the Drive environment. Running into a stack of different issues now but the 403 got solved.
I usually get a 403 when the API call was missing the Authorization http header. Trace the http and look at the headers. The rationale for the "quota" message is that without an Auth header, you are anonymous, and the quota for anonymous use is zero.
You might also check that your app is registered for both of the Drive APIs, as I've heard that that can cause the same problem.
On the internal method issue, that sounds like you're using incompatible library versions. What worked best for me was to delete all of the libraries I had downloaded with the sample code, then use the Google Eclipse plugin to "Google/Add Google APIs..." to download all of the latest versions.

Categories

Resources