Apps Script Execution API 404 error with devMode: true - rest

When requesting POST https://script.googleapis.com/v1/scripts/{script_id}:run with devMode: true I get a 404 error. I can run the script successfully with devMode: false.
Although other people (1, 2) have raised this issue, none of the other solutions work. I keep getting an HTTP 404 Not Found error whenever my request comes with devMode: true.
I have performed the following steps:
created a new Google account
created a Cloud project
set up an OAuth consent screen for the project
authorized the domain for the app (just in case)
created 'Desktop' OAuth2 credentials for this project with OAuth scopes listed below
enables Apps Script API on the project
created a standalone Apps Script using Google Drive ("Test 1")
set the Cloud Platform project ID for the script Test 1
deploy the script Test 1 as an API executable, with access to "Anyone"
obtain a valid access token with the exact same scopes listed below and used for the OAuth consent screen configuration in the Cloud project. The token is for the same account that owns the script and the cloud project.
After performing the above steps, running with devMode: false was successful, but when switching to devMode: true it failed.
The same happens when I set access to "Only Me".
To make clear the steps that I took, I provide a full flow of screenshots taken along the way (open image in new window to zoom in; the flows to top-to-bottom; the three columns from left to right are: Cloud console project flow; Apps Script flow; OAuth2 flow):
At the request of #ziganotschka I made a simpler copy of my Apps Script function:
function test() {
return 1;
}
And the appsscript.json manifest is:
{
"timeZone": "Asia/Jerusalem",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
The code for obtaining the OAuth2 token and running the script, in Python:
##
# %%
import requests
import urllib
import json
client_id = '...'
client_secret = '...'
script_id = '...'
is_dev_mode = True # True or False
##
# %% Initiate OAuth2
url = 'https://accounts.google.com/o/oauth2/auth?' + urllib.parse.urlencode({
'client_id': client_id,
'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob',
'response_type': 'code',
'scope': ' '.join([
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'openid',
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.scripts',
'https://www.googleapis.com/auth/script.external_request',
'https://www.googleapis.com/auth/script.projects',
'https://www.googleapis.com/auth/script.scriptapp',
'https://www.googleapis.com/auth/script.container.ui'
])
}, doseq=True)
print(url)
##
# %% Exchange authorization code with access and refresh tokens
print('Enter authorization token: ', end='')
authorization_code = input()
authorization_token_response = requests.post('https://accounts.google.com/o/oauth2/token', data={
'code': authorization_code,
'client_id': client_id,
'client_secret': client_secret,
'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob',
'grant_type': 'authorization_code'
})
authorization_token_response.raise_for_status()
authorization_data = authorization_token_response.json()
access_token = authorization_data["access_token"]
refresh_token = authorization_data["refresh_token"]
##
# %%
response = requests.post(f'https://script.googleapis.com/v1/scripts/{script_id}:run',
data=json.dumps({
"function": "test",
"parameters": [],
"devMode": is_dev_mode
}),
headers={
'content-type': 'application/json',
'authorization': f'Bearer {access_token}'
}
)
response.raise_for_status()
print(response.content)
I get similar results for a curl call:
$ curl 'https://script.googleapis.com/v1/scripts/x...x:run' -X POST -H 'content-type: application/json' -d '{"function":"test","parameters":[],"devMode":true}' -H 'authorization: Bearer x...x' --silent
{
"error": {
"code": 404,
"message": "Requested entity was not found.",
"status": "NOT_FOUND"
}
}
I consider this as an issue report, as Google mention that they use Stack Overflow to field technical questions for Apps Script API. As well as a beacon to anyone who has been frustrated with this issue.
Any my question would be -- am doing anything wrong?
As an aside question: what's the difference between substituting script_id for the Current API ID (as suggested in 'How to Execute a function guide'; this identifier seems to be identical to the script Project key under File > Project properties) and the Script's Drive file ID (suggested everywhere else; this seems to be identical to Script ID)?

Related

How do I get and download the contents of a file in GitHub using the REST API?

I am trying to use the GitHub API to retrieve and download the contents of a file in my GitHub repository to mimic how I am using the Azure DevOps REST API.
My ADO URL is:
https://dev.azure.com/<Org>/<Project>/_apis/git/repositories/<Repository>/items?versionType=branch&version=develop&path=<Path to file>/DEV1.yml&download=true
Above works perfectly fine and if I type that into my browser, it immediately downloads the DEV1.yml file.
I am trying to mimic this implementation using GitHub's REST API. My URL looks like:
https://api.github.com/repos/<Org>/<Repository>/contents/<Path to file>/DEV1.yml&download=true
This GitHub URL does not work in the browser, I assume it's because the repo is private and I need a token. However when I use curl:
curl -H "Authorization: Bearer <PAT>" https://api.github.com/repos/<Org>/<Repository>/contents/<Path to file>/DEV1.yml&download=true
This returns a large base64 encoded JSON object. I attempted to use the URL in place of the existing ADO one and it failed.
Are the 2 above URLs not the same?
Yes, it is different.
Github REST API download files has two steps.
1, The first step is get the download url.
The url format like this:
https://api.github.com/repos/<Project Name>/<Repository Name>/contents/<File Name>
The response format like this:
2, The second step is using the download url to get the file content.
The url format like this:
https://raw.githubusercontent.com/<Project Name>/<Repository Name>/main/<File Name>?token=<Random Token that related to Revision Version>
Please notice that the first step can't skip, otherwise you will be unable to get the revision token.
I can achieve your requirement using python:
import requests
#Define required information
project_name = "xxx"
repository_name = "xxx"
# repository_name = "xxx"
branch_name = "xxx"
File_name = "xxx"
PAT = "xxx"
url = "https://api.github.com/repos/"+project_name+"/"+repository_name+"/contents/"+File_name
#downoad file from github
payload = {}
headers = {
'Authorization': 'token '+PAT
}
#download file
file_content = requests.request("GET", ((requests.request("GET", url, headers=headers, data=payload)).json())['download_url'], headers=headers, data=payload)
print(file_content.text)
Successfully get the latest contents(I am also based on private repository):

PowerAutomate use REST API turn on reporting site collection feature

We can turn this feature on via PowerShell PnP, but need to do it via PowerAutomate REST API call.
I have the following for our FLOW REST API call.
Site Address >> https://MYCO.sharepoint.com/sites/Sandbox
Method >> POST
URI >> /_api/web/features
Headers:
-accept : application/json;odata.metadata=none
-content-type : application/json
BODY:
{
"url": "https://MYCO.sharepoint.com/sites/Sandbox/_api/web/features/add('7094bd89-2cfe-490a-8c7e-fbace37b4a34')"
}
When I run the FLOW I get:
Error
Action 'Send_an_HTTP_request_to_SharePoint' failed
Invalid request.
clientRequestId: 690efeb4-ddce-49a2-b5d7-58e5e06db54a
serviceRequestId: 94ea649f-80ce-b000-973f-9686227e5f12
Try giving entire thing in URI and leave body blank
Site Address >> https://MYCO.sharepoint.com/sites/Sandbox
Method >> POST
URI >> /_api/web/features/add('7094bd89-2cfe-490a-8c7e-fbace37b4a34')
Headers:
-accept : application/json;odata.metadata=none
-content-type : application/json
BODY:

POST URL with REST API token in vbs without password

I'm launching build jobs on a local Jenkins with:
curl -X POST "http://UID:TOKEN#server:port/job/DevGate/build?delay=0sec&json=%7B%22parameter%22%3A+%7B%22name%22%3A+%22DEVGATE_PACKAGELIST%22%2C+%22value%22%3A+%2212345678%3A9%22%7D%2C+%22statusCode%22%3A+%22303%22%2C+%22redirectTo%22%3A+%22.%22%7D&Submit=Build"
which translates into
curl -X POST "http://UID:TOKEN#server:port/job/DevGate/build?delay=0sec&json={"parameter": {"name": "DEVGATE_PACKAGELIST", "value": "12345678:9"}, "statusCode": "303", "redirectTo": "."}&Submit=Build"
UID being userID. TOKEN being API Token given by Jenkins/REST API. And it works. Now, this command is launched inside of a VBScript that mainly gathers data for creation of aforementioned URL. No password needed, and I'd like to keep it that way. The problem: I'd like to avoid using curl and use just native VBScript functionality.
What I've tried so far:
Dim http: Set http = CreateObject("Microsoft.XMLHTTP")
Dim url: url = "http://server:port/job/DevGate/build"
Dim data: data = "delay=0sec&json=%7B%22parameter%22:+%7B%22name%22:+%22DEVGATE_PACKAGELIST%22,+%22value%22:+%22" + the rest of data
'string2try = Base64EncodeString("UID:TOKEN")
'string2try = Base64EncodeString("UID:PASSWORD")
With http
.Open "POST", url, False
Call .SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
Call .SetRequestHeader("oAuth", token)
.Send data
'Call .SetRequestHeader("X-Api-Key", token)
'Call .SetRequestHeader("Authorization", "Bearer " & token)
'Call .SetRequestHeader("X-Auth-Token", token or string2try)
'Call .SetRequestHeader("X-Parse-REST-API-Key", token)
End With
Every permutation of that code fails authentication. How to pass my token + uid properly in VBScript without using curl?

Github REST API full example

I would like to create a new file in the my github repository by using github REST API. I've found following link, but honestly I don't understand it((
As I understand, I could do POST
url: https://api.github.com/repos/MyUserName/MyRepositoryName
headers:
Accept: application/vnd.github.v3+json
body:
{
"message": "my commit message",
"committer": {
"name": "My name",
"email": "my email"
},
"content": "base64encoded"
}
But it doesn't work. Could you please, write
1) which url should I call
2) which headers this request should contains
3) what body should be
You were close:) Lets assume, that
1) your login: YourUsername
2) your access token: 123a321
3) repository to be updated: YourRepo
4) file to be created: file.txt
5) folder that will contains new file: f1/f2
According to those assumptions your request should be following:
type : PUT
url : https://api.github.com/repos/YourUsername/YourRepo/contents/f1/f2/file.txt
headers :
{
"Content-Type" : "application/vnd.github.v3+json",
"Authorization" : "token 123a321"
}
body :
{
"message": "my commit message",
"committer": {
"name": "My name",
"email": "my email"
},
"content": "base64encoded"
}
UPD
If you write in java, you can use GitHubFileAPI library, that I recently pushed to the maven central repository.
Solution: In order to perform action on github api you can use curl
according to Github doc:
first make sure you have specific privileges and authentication token generated to your account in order to interact with Github api:
profile Settings -> Developer Settings -> Personal access tokens -> Generate new token
the command should be in http PUT method on path /repos/:owner/:repo/contents/:path
The required params for editing or adding new files (according to api)
message (String), Content (String) and sha(String), additional params are branch(String) commiter(String) and author(String)
Lets perform some curl message in order to perform your action, the simple formula for this case would be:
curl --user <userName>:<token>
--data '{"key":"value"}'
--header <HeaderType>
--request <HTTPMethod>
<fullURL>
for demonstration lets fill some details:
curl --user johnDoe:abc123!##
--data '{"message":"my message","content":"my content","sha":"abcjfhtenf736gd843ji43903"}'
--header Content-Type:application/json
--request PUT
https://api.github.com/repos/MyOrganization/MyCoolApp/contents/app/models
Verify on Github the content has been inserted correctly to your branch

Bash/Curl example of pocket oAuth login

I'm trying to get a simple bash script working with the pocket api. All I want to do is authenticate with pocket and download my list of articles (actually, only the count)
I'm a little confused by the way that the oauth process works.
I've registered my app with the pocket api and have a consumer key
its marked as in "development" - I'm not sure if this is important.
The bit that's confusing me is that it seems that the way that the oAuth flow works with it's redirect uris is that it only really works with a gui (i.e a browser) - is it possible to do this with a bash script?
Here is what I have below. it works up until I have the TOKEN, but then I'm not sure what to do next.
#!/bin/bash
REDIR="redirect_uri=pocketapp1234:authorizationFinished"
KEY=21004-xxxxxxabcabcabc # you can assume this is the consumer key pocket issues for my app.
CODE=`curl -X POST --data "consumer_key=$KEY&$REDIR" https://getpocket.com/v3/oauth/request`
echo "OK - code is $CODE"
TOKEN=$(echo $CODE | awk -F"=" '{print $2}')
echo "OK - token is $TOKEN"
AUTH="consumer_key=$KEY&$CODE"
# This line seems not to work
curl -v "https://getpocket.com/auth/authorize?request_token=$TOKEN&$REDIR"
Yes, the browser portion is required. At the authorize phase, there is a page from getpocket.com prompting the user to login and authorise the bash script to access the user's Pocket account.
You can refer to Step 3 of the Pocket API Docs.
This is the Python v3.8 script I'm using and seems to work.
#!/usr/bin/env python
from os import environ as env
import requests
import webbrowser
def authorize_pocket_app():
data = {
"consumer_key": env['POCKET_CONSUMER_KEY'],
"redirect_uri": env['POCKET_APP_NAME'],
}
resp = requests.post(url="https://getpocket.com/v3/oauth/request", data=data)
code = resp.text.split("=")[1]
webbrowser.open(f"https://getpocket.com/auth/authorize?request_token={code}"
"&redirect_uri=https://duckduckgo.com")
input("Authorize %s app in the browser, then click enter" % env['POCKET_APP_NAME'])
get_token(code)
def get_token(code):
resp = requests.post(
url="https://getpocket.com/v3/oauth/authorize",
data={
"consumer_key": env["POCKET_CONSUMER_KEY"],
"code": code,
})
token = resp.text.split("&")[0].split("=")[1]
print("Secret token:", token)
if __name__ == "__main__":
authorize_pocket_app()
To use it as is you need to install requests external library and export POCKET_CONSUMER_KEY and POCKET_APP_NAME in your shell environment. E.g.
pip install requests
export POCKET_CONSUMER_KEY=xxx-yyy-zzz
export POCKET_APP_NAME=my-pocket-app
python <filename>.py
HTH