How to pass string value as request body to the post method of third party API - go

I am trying for call external API call using POST method,
So for above POST API call i am facing an issue for content body not able to pass file path weblink as parameter.
postBody, _ := json.Marshal(map[string]string{
"www://xyz.org/file.txt",
})
requestBody := bytes.NewBuffer(postBody)
` resp, err := http.Post(("--POST API call--", "application/json", requestBody )
`
So if requestBody will fetch POST API call then, it should be allow to pass as a parameter with content body.
but its creating issue as below I have attached Postman snap where we can get to know content body is passing as null which should be like value of "www://xyz.org/file.txt"
normally POST call having requestBody body like below
postBody, _ := json.Marshal(map[string]string{
"Key1": "Value1",
"key2": "Value2",
})
**But in my case as below **
whichever file path I am calling that pass as a default web url value without key
postBody, _ := json.Marshal(map[string]string{
"www://xyz.org/file.txt",--------> // here no key available, only value as a string value
})

Related

Golang: Getting the response-redirect URL from an HTTP response

I'm trying to make a HTTP request using http.Get(url) in Go and I want to open the response in a browser. I'm using browser.OpenURL() to launch the system browser, but I cannot figure out how to obtain the response url.
In Python, using the requests library, it is an attribute of the response object.
I can obtain and open it in a browser (using the browser library) like so:
response = requests.get(endpoint)
browser.open(response.url)
How can I accomplish this using http/net library in Go? The response object is a struct that doesn't contain that attribute.
I am trying to call the Spotify API to authenticate an app, and this requires opening a browser window for user input. So far I've got this:
func getAuth(endpoint *url.Url) {
request, _ := http.NewRequest("GET", endpoint.string(), nil)
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
panic(err)
}
headers := resp.Header
page, _ := ioutil.ReadAll(resp.Body)
Where can I obtain the response URL or how can I handle the response so that it opens it in a browser?
Go will update the Request struct on the response if there is a redirect.
resp.Request.URL is what you are looking for.
// Request is the request that was sent to obtain this Response.
// Request's Body is nil (having already been consumed).
// This is only populated for Client requests.
Request *Request
Just get the redirect URL from response header.
redirectURL := resp.Header.Get("Location")

Validating HTTP request to check if contains all the required fields

I am using gin for creating a http server. I want to validate each and every HTTP request before I start calling my other functions.
I created a following struct named CreateUser to validate all incoming HTTP POST requests for CreateUser
type CreateUser struct {
FirstName string `validate:"min:2, regexp=^[a-zA-Z]*$"`
LastName string `validate:"min:2, regexp=^[a-zA-Z]*$"`
Email string `validate:"min:10, max=255 regexp=^[0-9a-zA-Z]*#[a-z]*$"`
}
The following function gets called when a request for UserCreate happens. But even if I do not send the firstName in the post request. The validation passes without an error. What could be the reason for this? How could I validate each and every HTTP request for it schema?
func (uhc UserHttpController) UserCreate(ctx *gin.Context) {
var createUser config.CreateUser
if err := ctx.BindJSON(&createUser); err != nil {
// send the bad request response
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
createdUser := InitUserController(uhc.globalVars).UserCreate(createUser)
ctx.JSON(http.StatusOK, gin.H{
"data": createdUser,
})
}
I tried without sending lastName in POST request body but on debugging the LastName is initialized to "" empty string and thus no error occurs.

Making POST request in Go with formdata and authentication

I'm currently trying to interface with an OAuth api with the example curl command curl -u {client_id}:{client_secret} -d grant_type=client_credentials https://us.battle.net/oauth/token. My current go file is:
package main
import (
"bytes"
"fmt"
"mime/multipart"
"net/http"
)
func checkErr(err error) bool {
if err != nil {
panic(err)
}
return true
}
func authcode(id string, secret string, cli http.Client) string {
//un(trace("authcode"))
var form bytes.Buffer
w := multipart.NewWriter(&form)
_, err := w.CreateFormField("grant_type=client_credentials")
checkErr(err)
req, err := http.NewRequest("POST", "https://us.battle.net/oauth/token", &form)
checkErr(err)
req.SetBasicAuth(id, secret)
resp, err := cli.Do(req)
checkErr(err)
defer resp.Body.Close()
json := make([]byte, 1024)
_, err = resp.Body.Read(json)
checkErr(err)
return string(json)
}
func main() {
//un(trace("main"))
const apiID string = "user"
const apiSecret string = "password"
apiClient := &http.Client{}
auth := authcode(apiID, apiSecret, *apiClient)
fmt.Printf("%s", auth)
}
When I run this I get a response of {"error":"invalid_request","error_description":"Missing grant type"}
For reference, the api flow states:
"To request access tokens, an application must make a POST request with the following multipart form data to the token URI: grant_type=client_credentials
The application must pass basic HTTP auth credentials using the client_id as the user and client_secret as the password."
and the expected response is a json string containing an access token, token type, expiration in seconds, and the scope of functions available with said token
From curl manual we have:
-d, --data <data>
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and
presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to
-F, --form.
Note the content-type application/x-www-form-urlencoded part.
as opposed to:
-F, --form <name=content>
(HTTP SMTP IMAP) For HTTP protocol family, this lets curl emulate a filled-in form in which a user has pressed the submit button. This causes curl to
POST data using the Content-Type multipart/form-data according to RFC 2388.
Therefore based on your curl, mime/multipart is probably not what you're looking for and you should be using Client.PostForm, from the manual of which we have:
The Content-Type header is set to application/x-www-form-urlencoded. To set other headers, use NewRequest and Client.Do.

Fetch POST Parameters in Golang with header as application/json

I am new to golang and trying to create REST API with POST Method using httprouter (https://github.com/julienschmidt/httprouter).
I am using simple raw request with header as Content-Type : application/json.
I have tried hard but not getting way to fetch raw query parameters.
req.FormValue("name") or req.Form.Get("name") is working fine but with header as Content-Type : application/x-www-form-urlencoded
Has anyone tried fetching raw query parameters(with header as Content-Type : application/json)?
use Json decode:
req is *http.Request
decoder := json.NewDecoder(req.Body)
decoder.UseNumber()
err := decoder.Decode(&yourStruct)
You need to grab the query params out of the URL.
// req *http.Request
params := req.URL.Query()
myParam := params["my-query-param"]
docs here

illegal base64 data at input byte 0 in go

I am starting with go and jwt.
For testing purpose I have a hardcoded secret.
And a route to get the key
const secretKey = "YOLOSWAG"
var mySigningKey = []byte(secretKey)
var GetTokenHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = jwt.MapClaims{
"admin": true,
"name": "John Doe",
"exp": time.Now().Add(time.Hour * 24).Unix(),
}
tokenString, _ := token.SignedString(mySigningKey)
w.Write([]byte(tokenString))
})
var jwtMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return mySigningKey, nil
},
SigningMethod: jwt.SigningMethodHS256,
})
and later added the jwtMiddleware to my route
r.Handle("/protected", jwtMiddleware.Handler(ProtectedTestHandler)).Methods("GET")
So localhost:3000/protected will output an error Required authorization token not found
this works.
/token will output my token. This works too.
And finally /protected with (in postman) Authorization: Bearer {token}
Will output illegal base64 data at input byte 0
I am really confused why this happens.
Don't use curlies around your token. The documentation in many places is confusing because it wraps your token in curlies. It's meant to represent a placeholder. You're not actually supposed to wrap your token with them. Do NOT do it like this.
Bearer {my-special-token}
It should be done like this
Bearer my-special-token
I'm an absolute newb with GO at the moment as I'm learning this right now but I ran into this same issue and realized that the code I was using to pull the JWT Token out of the Authorization header was leaving a blank space as the first character of the JWT token string. This was presumably causing the string not be base64 decoded.
This was the offending code which was leaving a blank space in front of the. JWT token:
This removed the first 6 chars instead of 5 from the Authorization header to correct the problem.
I ran into this problem when following the tutorial here: https://medium.com/wesionary-team/jwt-authentication-in-golang-with-gin-63dbc0816d55
Repo: https://github.com/Bikash888/jwt-auth

Resources