Google docs API: can't download a file, downloading documents works - oauth

I'm trying out http requests to download a pdf file from google docs using google document list API and OAuth 1.0. I'm not using any external api for oauth or google docs.
Following the documentation, I obtained download URL for the pdf which works fine when placed in a browser.
According to documentation I should send a request that looks like this:
GET https://doc-04-20-docs.googleusercontent.com/docs/secure/m7an0emtau/WJm12345/YzI2Y2ExYWVm?h=16655626&e=download&gd=true
However, the download URL has something funny going on with the paremeters, it looks like this:
https://doc-00-00-docs.googleusercontent.com/docs/securesc/5ud8e...tMzQ?h=15287211447292764666&amp\;e=download&amp\;gd=true
(in the url '&amp\;' is actually without '\' but I put it here in the post to avoid escaping it as '&').
So what is the case here; do I have 3 parameters h,e,gd or do I have one parameter h with value 15287211447292764666&ae=download&gd=true, or maybe I have the following 3 param-value pairs: h = 15287211447292764666, amp;e = download, amp;gd = true (which I think is the case and it seems like a bug)?
In order to form a proper http request I need to know exectly what are the parameters names and values, however the download URL I have is confusing. Moreover, if the params names are h,amp;e and amp;gd, is the request containing those params valid for obtaining file content (if not it seems like a bug).
I didn't have problems downloading and uploading documents (msword docs) and my scope for downloading a file is correct.
I experimented with different requests a lot. When I treat the 3 parameters (h,e,gd) separetaly I get Unauthorized 401. If I assume that I have only one parameter - h with value 15287211447292764666&ae=download&gd=true I get 500 Internal Server Error (google api states: 'An unexpected error has occurred in the API.','If the problem persists, please post in the forum.').
If I don't put any paremeters at all or I put 3 parameters -h,amp;e,amp;gd, I get 302 Found. I tried following the redirections sending more requests but I still couldn't get the actual pdf content. I also experimented in OAuth Playground and it seems it's not working as it's supposed to neither. Sending get request in OAuth with the download URL responds with 302 Found instead of responding with the PDF content.
What is going on here? How can I obtain the pdf content in a response? Please help.

I have experimented same issue with oAuth2 (error 401).
Solved by inserting the oAuth2 token in request header and not in URL.
I have replaced &access_token=<token> in the URL by setRequestHeader("Authorization", "Bearer <token>" )

Related

Twitter API v1.1 media INIT error code 32

I am trying to get the media_id for a media upload. See docs here.
When using postman, my request is processed successfully and I get a response like this:
{
"media_id": 1222234872222222401,
"media_id_string": "1222734822222102201",
"expires_after_secs": 86399
}
Unfortunately, using postman for our app is not an option. However, when I post a tweet with just text, the tweet is posted successfully using our own native code. I have also recreated the request from postman, and can successfully recreated the same oauth_signature needed for the media upload authorization. So I know that the backend is working in that I can create valid credentials, but I think I need some help structuring the POST request itself.
Here is the code (Lucee ColdFusion):
mediaEndpoint = "https://upload.twitter.com/1.1/media/upload.json?command=INIT&total_bytes=10240&media_type=image/jpg&oauth_consumer_key=consumerKeyHere&oauth_token=tokenHere&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1653075352&oauth_nonce=UU5V18WLaPN&oauth_version=1.0&oauth_signature=verifiedSignature";
cfhttp(url=mediaEndpoint, method="POST", result="init") {
cfhttpparam(type="header", name="Content-Type", value="application/x-www-form-urlencoded");
cfhttpparam(type="header", name="Accepts", value="*/*");
cfhttpparam(type="header", name="Accept-Encoding", value="gzip, deflate, br");
cfhttpparam(type="header", name="Connection", value="keep-alive");
cfhttpparam(type="body", value="command=INIT&media_type=#mediaParameters.media_type#&total_bytes=#mediaParameters.total_bytes#");
}
But I keep getting the following 401:
{"errors":[{"code":32,"message":"Could not authenticate you."}]}
I believe you're supposed to send your authorization token in the header. You're sending it in the URL as a query string. Twitter's documentation would indicate you need to include an authorization header as such:
cfhttpparam(type="header", name="Authorization", value="Bearer: #YourAccessToken#");

What format of url is this with the colon almost in the end - https://speech.googleapis.com/v1p1beta1/speech:longrunningrecognize

I am trying to consume the google text to speech api here : https://cloud.google.com/speech-to-text/docs/async-recognize#speech-async-recognize-gcs-protocol
and it has this url format below
https://google-speech-api-base-urlspeech:longrunningrecognize
What is this URL format with colon(:)in the end?
When I try to hit this URL, it gives me an error specifically while running test case on it .e. Invalid URI. Invalid Port?
But the official google documentation says this is a valid url? How to use this?
This format of URL is called gRPC Transcoding syntax. Your first URL is invlaid , because it's in the first path segment of a relative-path reference.
https://google-speech-api-base-urlspeech:longrunningrecognize
This url is invalid for usage, whereas the one below, https://speech.googleapis.com/v1/speech:longrunningrecognize was running fine.
Try changing your URL to something like
https://google-speech-api-base-url/speech:longrunningrecognize. It will work.
I looked at the documentation page you referenced and was unable to see/find a URL that looked like:
https://google-speech-api-base-urlspeech:longrunningrecognize
However, what I did find was a URL of the form:
https://speech.googleapis.com/v1/speech:longrunningrecognize
which looks perfectly valid.
The documentation for this REST request can be found here:
https://cloud.google.com/speech-to-text/docs/reference/rest/v1/speech/longrunningrecognize
Could you have made an error in your reading and comprehension?
Apparently the colon (:) is legal in the path part of a URL:
Are colons allowed in URLs?

Debugging an API request

I'm trying to post a user status update to the Goodreads API.
Most of the time my request returns 200 OK and does nothing. Every now and then, though, it returns 201 Created and the status is updated. When it works it's always the first time I try to make the call after running the app in iOS simulator. Subsequent calls never work.
I don't think the problem is the API itself, since the official Goodreads iOS app uses the same call and it always works.
Their API is famous for having problems with calls that include brackets in the parameters, but I can make other calls that contain brackets and they work fine, the problem is just this one.
I'm using OAuthSwift and this is my code:
oAuth.client.post(
"http://www.goodreads.com/user_status",//.xml",//?user_status[book_id]=6366035&user_status[page]=168",
parameters: ["user_status[page]" : 168, "user_status[book_id]" : 6366035, "format" : "xml"],
//headers: ["Content-Type" : "application/x-www-form-urlencoded"],
success: {
data, response in
print("")
print(response)
},
failure: {
error in
print("")
print(error)
}
)
(The commented out parts are alternatives I have tried unsuccessfully.)
I'm printing the base string that gets signed and it looks the same for the calls that work and the ones that don't, except for the nonce and the timestamp, obviously.
In the headers is also included the oauth_signature, which changes every time and sometimes contains characters that are encoded by OAuthSwift, so that could account for the call working just some of the time (it could work only when the signature doesn't contain a certain character)… but I'm printing out the headers too and I don't see any patterns or any discernible difference between the headers of the calls that work and those of the calls that don't.
So now I don't know what to test anymore… I'm checking the base string and the headers for calls that work and for calls that don't and they look the same… Could anybody think of something else that changes between calls and I should check? I have no idea what could be causing this and I don't know how to debug it.
Thanks in advance,
Daniel
Edit: Very weird… I tried my request with Paw, a Mac REST client, and with Chrome's Postman extension. If I use https I get 404 on my first call, then 201 on the second, then 404 on the third, 201 on the forth and so on. It works every other time. The time it works it doesn't matter if I use http or https, it works as long as there was a failed https request just before.
So I tried doing the same in my app: I added two https calls one after the other… in my app they always return 404.
So it seems like Postman, Paw and OAuthSwift are handling the requests differently. I don't know what could be the difference between those clients… the signature base string seems to be the same for all three, the headers too… so what else could change between them?
In the newer versions of Xcode you can only communicate with a HTTPS server. I expect Google support that so you can change the URL. Or you can edit your Info.plist file.
App Transport Security Settings > Allow Arbitrary Loads > YES

Desire2Learn Valence API | JSON not loading

I'm using the Python Requests library with the Valence-provided Python SDK to attempt to do a GET request. Something odd is happening with the URL and I'm not sure what. The response I get is 200 (which leads me to believe that the authentication is working), but when I try to print the JSON from the Request object, it instead prints the HTML of the page instead of the JSON.
I'm using modified code that I read from http://docs.valence.desire2learn.com/clients/python/auth.html.
Here's the Python code:
import requests
import auth as d2lauth
from auth import *
app_creds = { 'app_id': '----', 'app_key': '----' }
ac = d2lauth.fashion_app_context(app_id=app_creds['app_id'], app_key=app_creds['app_key'])
auth_url = ac.create_url_for_authentication('ugatest2.view.usg.edu', 'http://localhost:8080')
redirect_url = "https://localhost:8080?x_a=3----&x_b=3dMRgCBAHXJDTA2E6DJIfdWq-gYl-pk77fF_3X5oDUuqc"
uc = ac.create_user_context(auth_url, 'ugatest2.view.usg.edu', True)
route = 'ugatest2.view.usg.edu/d2l/api/versions/'
url = uc.create_authenticated_url(route)
r = requests.get(url)
print(r.text)
The output is the HTML of a page instead of JSON. If I do print(r), I get a status of 200. I think my redirect URL may be the issue, but I'm not sure what exactly is wrong. Thanks for any help!
Two things look off to me:
Using auth_url to create a user context isn't going to work, that's the URL you need to send the user to so they can authenticate. You need to use the URL you were redirected to after authenticating to build the user context. Assuming redirect_url is that URL, you should be passing that to create_user_context and not auth_url.
ugatest2.view.usg.edu/d2l/api/versions/ is not a valid value for passing to create_authenticated_route, /d2l/api/versions is probably what you want. The SDK will prepend the scheme, domain, and port so including those in the value passed is going to result in an incorrect URI.
Once your app is working properly, you'll be able to access a JSON response by using r.json() rather than r.text.

Gzip decompress JSON POST body in Rails/Passenger/Nginx

We have a function in our Rails code that accepts a JSON POST body:
contacts = ActiveSupport::JSON.decode(request.raw_post.gsub("+", ""))
(I'm aware that I can get this from params["_json"] as well, but we have extremely large (MBs) POST bodies that do not get put into params["_json"] for some reason (and + throws errors too).
Since the JSON is usually sent from a mobile client, it's important to us to optimize the upload size. We want to switch to having the POST body gzipped.
However, no matter what we do, we get the same error with no line number:
MultiJson::DecodeError (743: unexpected token at ''):
We have tried:
gzipped_contacts = Zlib::GzipReader.new(StringIO.new(request.raw_post)).read
contacts = ActiveSupport::JSON.decode(gzipped_contacts.gsub("+", ""))
This:
gzipped_contacts = ActiveSupport::Gzip.decompress(request.raw_post)
contacts = ActiveSupport::JSON.decode(gzipped_contacts.gsub("+", ""))
And the solution found here: Rails: how to unzip a compressed xml request body?
I'm pretty sure this is not occurring at the controller level because I can't log anything there, so it needs to be done in the middleware or at the server (but I can't find anything for Nginx that lets us deflate). Please assist!
Ok, turns out the iPhone client was sending the wrong headers. So the solution for anyone encountering this is to see the advice here:
Rails: how to unzip a compressed xml request body?
And verify that you are sending Content-Type: gzip/json.

Resources