NextPageToken gives invalid input error, 400 - Google Directory API ChomeDevices - google-api

I have to fetch 250K chromebooks from google workspace (Gsuite), I am using Admin Directory API to retrieve JSON data from Google.
The response returns in chunks of 200 records, in the response is included a nextPageToken, I use that next page token to retrieve the next 200 and so on.
After an hour, of using the nextPageToken attached from the previous request, However Google returns with error 400,
{error_code: 400, "message"=>"Invalid Input: CMiJhq7-5ewCEp0BCm737N8GN......"},
Note: This string 'CMiJhq7-5ewCEp0BCm737N8GN......' which google is calling as invalid is the nextPageToken.
Why is this happening? Does nextPageToken expire after 1 hour?
My code snippet:
query_list = {
'maxResults' => 200,
'access_token' => access_token,
'pageToken' => next_page_token
}
HTTParty.get(endpoint_url, query: query_list)

The nextPage token is created when the initial request is sent. This token is used in order to get the next batch of rows from the request.
This token is intended to be used immediately as the data associated with the initial request may be changed if you wait to long.
So yes next page tokens do expire i would actually expect them to expire in a lot less than an hour. I also wonder if the next page token wouldn't just expire after you used it the first time.
If you want to make the same request again i suggest you do that and get new next page tokens built for you after the hour.

I had to change my approach, initially, I fetched 200 chunks from Google API, performed some time-taking processing and then made entries into my database (database-intensive tasks) and then requested the next 200 chunks and so so. After an hour, the last nextpagetoken sent by Google became invalid.
So, now I fetch 200 chunks, save them to my database in JSON format without performing any database-intensive tasks, request the next 200, and so on. I was able to fetch 300K Chromebooks JSON data from google in around 56 Minutes before the nextPageToken became invalid.
I am now processing that JSON data present in my database, without having network overhead or any google API dependency.

I'm encountering error Error 400: Invalid Value, invalid when I tried to use pageToken parameter of the Google Calendar Events API.
The code (in Go) I was using.
call := service.Events.List(calendarID).SingleEvents(true)
events, err := call.Do()
if err != nil {
return err
}
var allEvents []*calendar.Event
allEvents = append(allEvents, events.Items...)
if events.NextPageToken != "" {
nextPageToken := events.NextPageToken
nextCall := service.Events.List(calendarID).SingleEvents(true).PageToken(nextPageToken)
events, err = nextCall.Do()
if err != nil {
return err
}
allEvents = append(allEvents, events.Items...)
}
As illustrated in Paging through lists of resources, the next API call has to be exactly the same as the previous one. Thus, the following code works with the pageToken (where no nextCall is being used).
call := service.Events.List(calendarID).SingleEvents(true)
events, err := call.Do()
if err != nil {
return err
}
var allEvents []*calendar.Event
allEvents = append(allEvents, events.Items...)
if events.NextPageToken != "" {
nextPageToken := events.NextPageToken
call := call.PageToken(nextPageToken)
events, err = call.Do()
if err != nil {
return err
}
allEvents = append(allEvents, events.Items...)
}

Related

I add file to my API and got invalid character '-' in numeric literal in POST API

I know this code need to send a JSON instead of form data in the API
err := ctx.ShouldBindJSON(&modelAdd)
if err != nil {
return err
}
But I need to add file, is there anything like ShouldBindJSON but for FormData?
You can use ShouldBind to get data from form data as the documentation says
https://github.com/gin-gonic/gin#model-binding-and-validation

Go-zabbix library does not find existing Event by id

I am trying to get an Event with a given event_id from Zabbix via the library github.com/cavaliercoder/go-zabbix.
An event with this id exists and is currently active. Connection to Zabbix is successful. Moreover, if I remove the EventIDs filter, it finds more than 600 events. But (!) I cannot access some of them directly from the Zabbix web interface under the same user.
Code:
session, err := zabbix.NewSession("zabbix_url/api_jsonrpc.php", "user", "password")
if err != nil {
panic(err)
}
var event_ids []string = []string{"2589270"}
params := zabbix.EventGetParams{
EventIDs: event_ids,
}
events, err := session.GetEvents(params)
fmt.Println(events)
Output:
[]
Errors:
2021/07/06 18:49:09 Error getting events: No results were found matching the given search
parameters
2021/07/06 18:49:09 No events found
2021/07/06 18:49:09 Validated 0 Events
Maybe I somehow incorrectly enter the id in the library?
In the source code of the library, the EventIDs parameter looks like this:
EventIDs []string `json:"eventids,omitempty"`
At the same time, everything works correctly from curl.
UPD
Code:
jparams, err := json.Marshal(params)
os.Stdout.Write(jparams)
Returns:
{"eventids":["2589270"],"object":0,"acknowledged":false}
UPD2:
It has been empirically established that the problem lies in the acknowledged parameter. If it is set to false, the event is not found. If it is set to true, the event is found. Curl exhibits the same behavior.
The problem is that the acknowledged parameter is set by default to either true or false. And I cannot remove it.
As planned by zabbix api (I guess), if this parameter is set to false, all events should be returned. If the parameter is set to true, then only acknowledged events should be returned. But it doesn't work as intended.

Google Drive API - List Permissions of a file

I am using the list permissions endpoint (https://developers.google.com/drive/api/v3/reference/permissions/list) to get all the permissions for a file that exists in a shared drive.
I am running into an issue with a file I have that lives in a shared drive. The file has 100 permissions. The max limit on the number of permissions returned for a shared drive file is 100, so I should only need to make one request to get all the permissions for the file and the API should not return a next page token.
But this is not the behaviour I am experiencing, after the first request I continuously get the same next page token back from the API.
So for the following code below (written in go), I get into an infinite loop, since I continuously get the same next page token back.
var permissionService PermissionsService := getPermissionsService()
fileID := "1234abcd"
nextPageToken := ""
anotherPage := true
permissions := []*Permission{}
for anotherPage {
result, err := permissionService.
List(fileID).
SupportsAllDrives(true).
SupportsTeamDrives(false).
Fields("*").
PageSize(100).
Do()
if err != nil {
panic(err)
}
anotherPage = result.NextPageToken != ""
nextPageToken = result.NextPageToken
permissions = append(permissions, result.Permissions...)
}
fmt.Println("Permissions", permissions)
Am I supposed to account for this case in my code? From the documentation, this is never mentioned so I assume this is not supposed to happen.
It seems that you did not add the PageToken parameter in your permissionService. You are actually requesting the same first 100 results of the permission service.
Not familiar with the language but something like this
for anotherPage {
result, err := permissionService.
List(fileID).
SupportsAllDrives(true).
SupportsTeamDrives(false).
Fields("*").
PageSize(100).
PageToken(nextPageToken).
Do()
if err != nil {
panic(err)
}
anotherPage = result.NextPageToken != ""
nextPageToken = result.NextPageToken
permissions = append(permissions, result.Permissions...)
}
Can you also verify first if the result.NextPageToken will return "" if the file has < 100 results, I used API explorer and Apps Script to access this API and the nextPageToken is not part of the response body when permission list is less than the pageSize.

Obtaining Calls for Entire Month

I want to page through an entire month's worth of Calls usage in a report. Unfortunately, I'm experiencing random 500 errors from the API.
First I initialize the first page call to /Calls.json
// Set initial baseUrl
urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Calls.json"
baseUrl, err := url.Parse(urlStr)
if err != nil {
panic(err)
}
// Build query parameters and URL
v := url.Values{}
v.Set("StartTime>", "2017-08-01")
v.Set("StartTime<", "2017-08-02")
v.Set("To", os.Args[1])
v.Set("PageSize", "1000")
v.Set("Page", "0")
baseUrl.RawQuery = v.Encode()
// Begin recursive call
pageNext(baseUrl)
I then determine if there is a "next page" by checking the response property next_page_uri, if the property is not blank then I proceed to recursively call the API with the previous calls next_page_uri query.
Each time I end up with a 500 error, sometimes within the first call and sometimes it is after 100-ish calls.
Is this really the best way to obtain such a report?

How to fetch body from imap server in Go

I successfully fetched a list of email headers using the sample code from this url: https://godoc.org/code.google.com/p/go-imap/go1/imap#example-Client . However, I still haven't been able to fetch the body of the emails. Can anyone show some working sample code that could fetch the body of the emails from a imap server in Golang?
I figured out how to get the body text now.
cmd, _ = c.UIDFetch(set, "RFC822.HEADER", "RFC822.TEXT")
// Process responses while the command is running
fmt.Println("\nMost recent messages:")
for cmd.InProgress() {
// Wait for the next response (no timeout)
c.Recv(-1)
// Process command data
for _, rsp = range cmd.Data {
header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
uid := imap.AsNumber((rsp.MessageInfo().Attrs["UID"]))
body := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"])
if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
fmt.Println("|--", msg.Header.Get("Subject"))
fmt.Println("UID: ", uid)
fmt.Println(string(body))
}
}
cmd.Data = nil
c.Data = nil
}
The example code you've linked to demonstrates the use of the IMAP FETCH command to fetch the RFC822.HEADER message data item for a message. The RFC contains a list of standard data items you can fetch from a message.
If you want the entire mime formatted message (both headers and body), then requesting BODY should do. You can get the headers and message body separately by requesting BODY[HEADER] and BODY[TEXT] respectively. Modifying the sample program to use one of these data items should get the data you are after.

Resources