Google Workspace Alert Center get/update settings calls returning 404 - google-workspace

Ref: https://developers.google.com/admin-sdk/alertcenter/reference/rest
The getSettings & updateSettings API calls there are returning 404.
Go code which was working till early January has started to fail at least since mid-January. The same service account credentials work correctly for calling list API call for e.g. I was wondering if this is a SDK issue and tried Python too, but seeing the same behaviour there.
On https://alertcenter.googleapis.com on a browser with no credentials:
/v1beta1/settings throws a 404 which isn't expected
/v1beta1/alerts throws a 401 correctly
Python code sample using google-api-python-client==2.75.0
# alert.py
from google.oauth2 import service_account
from googleapiclient.discovery import build
def main():
credentials = service_account.Credentials.from_service_account_file(
'service_account_credentials.json',
scopes=['https://www.googleapis.com/auth/apps.alerts'],
subject='<email of Google Workspace user authorized to manage alerts>'
)
# Build the service
service = build('alertcenter', 'v1beta1', credentials=credentials)
response = service.v1beta1().getSettings().execute()
# When uncommented, the below call works with the same credentials
# response = service.alerts().list().execute()
print(response)
if __name__ == '__main__':
main()
Golang code sample using google.golang.org/api v0.109.0
// alert.go
package main
import (
"context"
"crypto/tls"
"fmt"
"github.com/hashicorp/go-cleanhttp"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/alertcenter/v1beta1"
"io/ioutil"
"net/http"
"time"
)
func main() {
creds, err := ioutil.ReadFile("service_account_credentials.json")
if err != nil {
fmt.Println(err)
}
config, err := google.JWTConfigFromJSON(creds, alertcenter.AppsAlertsScope)
if err != nil {
fmt.Println(err)
}
config.Subject = "<email of Google Workspace user authorized to manage alerts>"
transport := cleanhttp.DefaultPooledTransport()
transport.TLSClientConfig = &tls.Config{
InsecureSkipVerify: false,
}
transport.ResponseHeaderTimeout = 30 * time.Second
hc := &http.Client{
Transport: transport,
}
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, hc)
client := config.Client(ctx)
srv, err := alertcenter.New(client)
if err != nil {
fmt.Println(err)
}
fmt.Println(srv)
s, err := srv.V1beta1.GetSettings().Context(ctx).Do()
// When uncommented, the below call works with the same credentials
// s, err := srv.Alerts.List().Context(ctx).Do()
fmt.Println(s)
fmt.Println(err)
}
What steps will reproduce the problem?
Get the service account credentials JSON file and substitute the path in the code
Get the Google Workspace user's email and substitute the subject in the code
python3 alert.py or go run alert.go
Expected/actual output
I used to get standard get & update settings 200 responses as mentioned in the documentation earlier. Now I get this with the Python code:
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://alertcenter.googleapis.com/v1beta1/settings?alt=json returned "Not Found". Details: "<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}#media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}#media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}#media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>That’s an error.</ins>
<p>The requested URL <code>/v1beta1/settings</code> was not found on this server. <ins>That’s all we know.</ins>
">
The Golang code also has a similar output now.

Related

How to get path and filename from postman request body using Go

This question already asked but it is not solve my issue.
In my Go project am not able to print path and filename. It is showing some error like below:
2021/10/13 16:25:07 http: panic serving [::1]:60170: runtime error: invalid memory address or nil pointer dereference goroutine 6 [running]:
My Postman collection
my code
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func encodeFfmpeg(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "multipart/form-data")
_, header, _ := r.FormFile("video")
fmt.Println(header.Filename)
}
func main() {
router := mux.NewRouter()
router.HandleFunc("/encode", encodeFfmpeg).Methods("POST")
// config port
fmt.Printf("Starting server at 8080 \n")
http.ListenAndServe(":8080", router)
}
Am trying to print filename with path eg: /home/ramesh/videos/video.mp4
The sent request is missing the boundary parameter in the Content-Type header. This parameter is required for multipart/form-data to work properly.
In Postman remove the explicit Content-Type header setting and leave it to Postman to automatically set the header with the boundary parameter.
For more see: https://stackoverflow.com/a/16022213/965900 & https://stackoverflow.com/a/41435972/965900
Last but not least, do not ignore errors.

Go API on Google App Engine with Postgres

I am trying to connect to my GAE Postgres SQL db using Go+Gin+PGX. I have the Postgres SQL api activated and this program runs on my local machine but does not run on GAE. I think it is not connecting the db via pgx but I am not sure.
main.go works on my local machine and instance of psql but after deploying to GAE cannot connect to db via the Public IP in GCP SQL instance. I have modified my working code to fix the MWE.
package main
import (
"fmt"
"os"
"github.com/gin-gonic/gin"
"github.com/jackc/pgx/v4"
"golang.org/x/net/context"
)
func main() {
conn, err := connectDB()
if err != nil {
os.Exit(1)
}
defer conn.Close(context.Background())
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
router.Run(":8080")
}
func connectDB() (c *pgx.Conn, err error) {
postgres := "postgresql://postgres:root#35.236.60.144:5432/goapi" //35.236.60.144
conn, err := pgx.Connect(context.Background(), postgres)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database:\n\t%v\n", err.Error())
return nil, err
}
err = conn.Ping(context.Background())
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to ping:\n\t%v\n", err.Error())
return nil, err
}
return conn, err
}
If I use Postman to perform a GET to GAE website then it I get
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>500 Server Error</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Server Error</h1>
<h2>The server encountered an error and could not complete your request.<p>Please try again in 30 seconds.</h2>
<h2></h2>
</body>
</html>
The corresponding GAE error stack trace sample is
runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0xaabec7]
at
github.com/jackc/pgx/v4.(*Conn).exec (conn.go:413)
at
github.com/jackc/pgx/v4.(*Conn).Exec (conn.go:396)
at
github.com/jackc/pgx/v4.(*Conn).Ping (conn.go:347)
at
main.connectDB (main.go:41)
at
main.main (main.go:15)
When I view the log I see...
Unable to connection to database: failed to connect to `host=35.236.60.144 user=postgres database=goapi`: dial error (dial tcp 35.236.60.144:5432: connect: connection timed out)

Golang HTTP POST succeeds, but it doesn't invoke a docker action

Problem: Although I can easily issue GET and POST commands from curl on my local docker socket, when I try to do the POST equivalent in Golang for a docker pull action, using net.Dial, I see no action taken on Docker's behalf.
Note that, meanwhile, the GET action works just fine using docker sockets via the golang client.
For example, when running the code at the bottom of this post, I see:
2018/01/05 14:16:33 Pulling http://localhost/v1.24/images/create?fromImage=fedora&tag=latest ......
2018/01/05 14:16:34 Succeeded pull for http://localhost/v1.24/images/create?fromImage=fedora&tag=latest &{200 OK 200 HTTP/1.1 1 1 map[Docker-Experimental:[true] Ostype:[linux] Server:[Docker/17.09.0-ce (linux)] Api-Version:[1.32] Content-Type:[application/json] Date:[Fri, 05 Jan 2018 19:16:34 GMT]] 0xc42010a100 -1 [chunked] false false map[] 0xc420102000 <nil>}
The code for attempting to do a pull via a POST action:
// pullImage is the equivalent of curl --unix-socket /var/run/docker.sock -X POST http://localhost/images/create?fromImage=alpine
func pullImage(img string, tag string) (err error) {
fd := func (proto, addr string) (conn net.Conn, err error) {
return net.Dial("unix", "/var/run/docker.sock")
}
tr := &http.Transport{
Dial: fd,
}
client := &http.Client{Transport: tr}
imageUrl := fmt.Sprintf("http://localhost/v1.24/images/create?fromImage=%s&tag=%s", img, tag)
log.Printf("Pulling %s ...... ", imageUrl)
resp, err := client.Post(imageUrl, "application/json", nil)
if resp.StatusCode == 200 && err == nil {
log.Printf("Succeeded pull for %s %v",imageUrl, resp)
} else {
log.Printf("FAILED pull for %s , ERROR = (( %s )) ",imageUrl , err)
}
return err
Question:
What does curl --unix-socket /var/run/docker.sock -X POST http://localhost/v1.24/images/create?fromImage=fedora do differently then the Golang code in the above snippet?
I figured this out. Actually, my prolem was that I wasn't completing the response body.
Adding
defer resp.Body.Close()
after the rest, err := client... clause was enough to finish triggering an entire pull. Not quite sure why closing the response body effects the ability of docker to start pulling the images down, but in any case, that was the case.

Not able to send mail in Golang

I am trying to send mail on my local system using gmail package of golang. For which I tried the following:
package main
import(
"fmt"
"github.com/SlyMarbo/gmail"
)
func main() {
email := gmail.Compose("Email subject", "Email body")
email.From = "account#gmail.com"
email.Password = "password"
// Defaults to "text/plain; charset=utf-8" if unset.
email.ContentType = "text/html; charset=utf-8"
// Normally you'll only need one of these, but I thought I'd show both.
email.AddRecipient("recepient#domain.com")
err := email.Send()
if err != nil {
fmt.Println(err)
// handle error.
}
}
I am neither getting any error nor mail. Not sure if it is not sent due to local server. Can anyone please guide me what am I missing? I took reference from this page.

Go HTTP Request with Basic Auth returning a 401 instead of a 301 redirect

Using Go 1.5.1.
When I try to make a request to a site that automatically redirects to HTTPS using Basic Auth I would expect to get a 301 Redirect response, instead I get a 401.
package main
import "net/http"
import "log"
func main() {
url := "http://aerolith.org/files"
username := "cesar"
password := "password"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Println("error", err)
}
if username != "" || password != "" {
req.SetBasicAuth(username, password)
log.Println("[DEBUG] Set basic auth to", username, password)
}
cli := &http.Client{
}
resp, err := cli.Do(req)
if err != nil {
log.Println("Do error", err)
}
log.Println("[DEBUG] resp.Header", resp.Header)
log.Println("[DEBUG] req.Header", req.Header)
log.Println("[DEBUG] code", resp.StatusCode)
}
Note that curl returns a 301:
curl -vvv http://aerolith.org/files --user cesar:password
Any idea what could be going wrong?
A request to http://aerolith.org/files redirects to https://aerolith.org/files (note change from http to https). A request to https://aerolith.org/files redirects to https://aerolith.org/files/ (note addition of trailing /).
Curl does not follow redirects. Curl prints the 301 status for the redirect from http://aerolith.org/files to https://aerolith.org/files/.
The Go client follows the two redirects to https://aerolith.org/files/. The request to https://aerolith.org/files/ returns with status 401 because the Go client does not propagate the authorization header through the redirects.
Requests to https://aerolith.org/files/ from the Go client and Curl return status 200.
If you want to follow the redirects and auth successfully, set auth header in a CheckRedirect function:
cli := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 10 {
return errors.New("stopped after 10 redirects")
}
req.SetBasicAuth(username, password)
return nil
}}
resp, err := cli.Do(req)
If you want to match what Curl does, use a transport directly. The transport does not follow redirects.
resp, err := http.DefaultTransport.RoundTrip(req)
The application can also use the client CheckRedirect function and a distinguished error to prevent redirects as shown in an answer to How Can I Make the Go HTTP Client NOT Follow Redirects Automatically?. This technique seems to be somewhat popular, but is more complicated than using the transport directly.
redirectAttemptedError := errors.New("redirect")
cli := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return redirectAttemptedError
}}
resp, err := cli.Do(req)
if urlError, ok := err.(*url.Error); ok && urlError.Err == redirectAttemptedError {
// ignore error from check redirect
err = nil
}
if err != nil {
log.Println("Do error", err)
}