Here is my console:
GET http://localhost:8080/api/photos.json?token=ABCDEFGHIJKLMNOPQRSTUVWXYZ
200 OK
0
jquery.js (line 8526)
|Params| Headers Response JSON
token ABCDEFGHIJKLMNOPQRSTUVWXYZ
I am in the params tab. How do I access this and, for example log token to my terminal window.
In node: request.param('token')
Just use func (*Request) FormValue
FormValue returns the first value for the named component of the query. POST and PUT body parameters take precedence over URL query string values. FormValue calls ParseMultipartForm and ParseForm if necessary. To access multiple values of the same key use ParseForm.
Simple Server
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", home)
http.ListenAndServe(":4000", nil)
}
func home(w http.ResponseWriter , r *http.Request) {
fmt.Fprint(w, "<html><body><h1>Hello ", r.FormValue("token") , "</h1></body></html>")
}
Visit localhost:4000/photos.json?token=ABCDEFGHIJKLMNOPQRSTUVWXYZ you would get
Hello ABCDEFGHIJKLMNOPQRSTUVWXYZ
I suppose you have a http.Request. Let's suppose it's called hr.
Then you can do
hr.ParseForm()
and after that you may use hr.Form which is defined like this :
// Form contains the parsed form data, including both the URL
// field's query parameters and the POST or PUT form data.
// This field is only available after ParseForm is called.
// The HTTP client ignores Form and uses Body instead.
Form url.Values
where url.Values is a map :
type Values map[string][]string
Here's an example of use of a parsed form where I'm only interested in the first value for a given name :
func getFormValue(hr *http.Request, name string) string {
if values := hr.Form[name]; len(values) > 0 {
return values[0]
}
return ""
}
Related
In my use-case, I need to post data to url, however the data itself is a query string.
Example:
curl -POST -d "username=abc&rememberme=on&authtype=intenal" "https..somemdpoint"
What I have is a method which takes in 3 values
function makePostRequest(username string, rememberme string, authtype string, endpoint string) {
// post a curl request.
}
I am struggling to find any library that would return me a query string if I provided it with parameters.
I tried doing this:
q := req.URL.Query()
q.Add("api_key", "key_from_environment_or_flag")
q.Add("another_thing", "foobar")
fmt.Print(q)
But realized it actually returns Values which is a map so its no good.
Is there any method in golang that creates a queryString ?
You almost got it. Call Values.Encode() to encode the map in URL-encoded form.
fmt.Print(q.Encode()) // another_thing=foobar&api_key=key_from_environment_or_flag
Create the map directly instead of using req.URL.Query() to return an empty map:
values := url.Values{}
values.Add("api_key", "key_from_environment_or_flag")
values.Add("another_thing", "foobar")
query := values.Encode()
Use strings.NewReader(query) to get an io.Reader for the POST request body.
So I'm receiving a request to my server that looks a little something like this
http://localhost:8080/#access_token=tokenhere&scope=scopeshere
and I can't seem to find a way to parse the token from the url.
If the # were a ? I could just parse it a standard query param.
I tried to just getting everything after the / and even the full URL, but with no luck.
Any help is greatly appreciated.
edit:
So I've solved the issue now, and the correct answer is you can't really do it in GO. So I made a simple package that will do it on the browser side and then send the token back to the server.
Check it out if you're trying to do local twitch API stuff in GO:
https://github.com/SimplySerenity/twitchOAuth
Anchor part is not even (generally) sent by a client to the server.
Eg, browsers don't send it.
For parse urls use the golang net/url package: https://golang.org/pkg/net/url/
OBS: You should use the Authorization header for send auth tokens.
Example code with extracted data from your example url:
package main
import (
"fmt"
"net"
"net/url"
)
func main() {
// Your url with hash
s := "http://localhost:8080/#access_token=tokenhere&scope=scopeshere"
// Parse the URL and ensure there are no errors.
u, err := url.Parse(s)
if err != nil {
panic(err)
}
// ---> here is where you will get the url hash #
fmt.Println(u.Fragment)
fragments, _ := url.ParseQuery(u.Fragment)
fmt.Println("Fragments:", fragments)
if fragments["access_token"] != nil {
fmt.Println("Access token:", fragments["access_token"][0])
} else {
fmt.Println("Access token not found")
}
// ---> Others data get from URL:
fmt.Println("\n\nOther data:\n")
// Accessing the scheme is straightforward.
fmt.Println("Scheme:", u.Scheme)
// The `Host` contains both the hostname and the port,
// if present. Use `SplitHostPort` to extract them.
fmt.Println("Host:", u.Host)
host, port, _ := net.SplitHostPort(u.Host)
fmt.Println("Host without port:", host)
fmt.Println("Port:",port)
// To get query params in a string of `k=v` format,
// use `RawQuery`. You can also parse query params
// into a map. The parsed query param maps are from
// strings to slices of strings, so index into `[0]`
// if you only want the first value.
fmt.Println("Raw query:", u.RawQuery)
m, _ := url.ParseQuery(u.RawQuery)
fmt.Println(m)
}
// part of this code was get from: https://gobyexample.com/url-parsing
Say I have this http handler:
func SomeHandler(w http.ResponseWriter, r *http.Request) {
data := GetSomeData()
_, err := w.Write(data)
}
Should I check the error returned by w.Write? Examples I've seen just ignore it and do nothing. Also, functions like http.Error() do not return an error to be handled.
It's up to you. My advice is that unless the documentation of some method / function explicitly states that it never returns a non-nil error (such as bytes.Buffer.Write()), always check the error and the least you can do is log it, so if an error occurs, it will leave some mark which you can investigate should it become a problem later.
This is also true for writing to http.ResponseWriter.
You might think ResponseWriter.Write() may only return errors if sending the data fails (e.g. connection closed), but that is not true. The concrete type that implements http.ResponseWriter is the unexported http.response type, and if you check the unexported response.write() method, you'll see it might return a non-nil error for a bunch of other reasons.
Reasons why ResponseWriter.Write() may return a non-nil error:
If the connection was hijacked (see http.Hijacker): http.ErrHijacked
If content length was specified, and you attempt to write more than that: http.ErrContentLength
If the HTTP method and / or HTTP status does not allow a response body at all, and you attempt to write more than 0 bytes: http.ErrBodyNotAllowed
If writing data to the actual connection fails.
Even if you can't do anything with the error, logging it may be of great help debugging the error later on. E.g. you (or someone else in the handler chain) hijacked the connection, and you attempt to write to it later; you get an error (http.ErrHijacked), logging it will reveal the cause immediately.
Tip for "easy" logging errors
If you can't do anything with the occasional error and it's not a "showstopper", you may create and use a simple function that does the check and logging, something like this:
func logerr(n int, err error) {
if err != nil {
log.Printf("Write failed: %v", err)
}
}
Using it:
logerr(w.Write(data))
Tip for "auto-logging" errors
If you don't even want to use the logerr() function all the time, you may create a wrapper for http.ResponseWriter which does this "automatically":
type LogWriter struct {
http.ResponseWriter
}
func (w LogWriter) Write(p []byte) (n int, err error) {
n, err = w.ResponseWriter.Write(p)
if err != nil {
log.Printf("Write failed: %v", err)
}
return
}
Using it:
func SomeHandler(w http.ResponseWriter, r *http.Request) {
w = LogWriter{w}
w.Write([]byte("hi"))
}
Using LogWriter as a wrapper around http.ResponseWriter, should writes to the original http.ResponseWriter fail, it will be logged automatically.
This also has the great benefit of not expecting a logger function to be called, so you can pass a value of your LogWriter "down" the chain, and everyone who attempts to write to it will be monitored and logged, they don't have to worry or even know about this.
But care must be taken when passing LogWriter down the chain, as there's also a downside to this: a value of LogWriter will not implement other interfaces the original http.ResponseWriter might also do, e.g. http.Hijacker or http.Pusher.
Here's an example on the Go Playground that shows this in action, and also shows that LogWriter will not implement other interfaces; and also shows a way (using 2 "nested" type assertions) how to still get out what we want from LogWriter (an http.Pusher in the example).
I want to add to #icza solution. You don't need to create logging structure, you can use simple function:
func logWrite(write func([]byte) (int, error), body []byte) {
_, err := write(body)
if err != nil {
log.Printf("Write failed: %v", err)
}
}
Take a look on that approach based on the #icza code: https://play.golang.org/p/PAetVixCgv4
func fupload(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
r.ParseForm()
company := r.FormValue("company")
fmt.Println(company)
_, header, _ := r.FormFile("upfile")
fmt.Println(header.Filename)
return
}
w.Write([]byte("<html><body>"))
w.Write([]byte(fmt.Sprintf("<form method=\"POST\" enctype=\"multipart/form-data\">")))
w.Write([]byte("Enter Company <input type=\"text\" maxlength=\"80\" size=\"80\" name=\"company\" ><br/>"))
w.Write([]byte("File to upload: <input type=\"file\" name=\"upfile\" /><br/>"))
w.Write([]byte("<input type=\"submit\" value=\"Submit\"/>"))
w.Write([]byte("</form>"))
w.Write([]byte("</body></html>"))
return
}
For the input type Text (eg) Company here always return NULL, when enctype="multipart/form-data"
ParseForm only parses the query parameters. From the docs:
ParseForm parses the raw query from the URL and updates r.Form.
For POST or PUT requests, it also parses the request body as a form
and put the results into both r.PostForm and r.Form. POST and PUT body
parameters take precedence over URL query string values in r.Form.
If the request Body's size has not already been limited by
MaxBytesReader, the size is capped at 10MB.
ParseMultipartForm calls ParseForm automatically. It is idempotent.
Either use ParseMultipartForm if you want to handle "multipart/form-data", or don't call either and let FormValue call what's needed.
Yes, you should use enctype="multipart/form-data". But you should not use ParseForm() method if you already use FormValue(key string) or FormFile(key string) method.
Request.FormFile
FormFile returns the first file for the provided form key. FormFile
calls ParseMultipartForm and ParseForm if necessary.
Request.FormValue
FormValue returns the first value for the named component of the
query. POST and PUT body parameters take precedence over URL query
string values. FormValue calls ParseMultipartForm and ParseForm if
necessary and ignores any errors returned by these functions. If key
is not present, FormValue returns the empty string. To access multiple
values of the same key, call ParseForm and then inspect Request.Form
directly.
<form action="/fupload" method="POST" enctype="multipart/form-data">
<input type="file" name="fileupload">
</form>
file, _, err := req.FormFile("fileupload")
switch err {
case nil:
defer file.Close()
fileData, err := ioutil.ReadAll(file)
//check err
case http.ErrMissingFile:
//do something
default:
//do something
}
I am writing some Go web services (also implementing the webserver in Go with http.ListenAndServe).
I have a map of structs which I would like to keep in memory (with an approximate data size of 100Kb) to be used by different HTTP requests.
How can this be achieved in Go? I am thinking to use global package variables or caching systems (like memcache/groupcache).
In addition to the answers you've already received, consider making use of receiver-curried method values and http.HandlerFunc.
If your data is data that is loaded before the process starts, you could go with something like this:
type Common struct {
Data map[string]*Data
}
func NewCommon() (*Common, error) {
// load data
return c, err
}
func (c *Common) Root(w http.ResponseWriter, r *http.Request) {
// handler
}
func (c *Common) Page(w http.ResponseWriter, r *http.Request) {
// handler
}
func main() {
common, err := NewCommon()
if err != nil { ... }
http.HandleFunc("/", common.Root)
http.HandleFunc("/page", common.Page)
http.ListenAndServe(...)
}
This works nicely if all of the Common data is read-only. If the Common data is read/write, then you'll want to have something more like:
type Common struct {
lock sync.RWMutex
data map[string]Data // Data should probably not have any reference fields
}
func (c *Common) Get(key string) (*Data, bool) {
c.lock.RLock()
defer c.lock.RUnlock()
d, ok := c.data[key]
return &d, ok
}
func (c *Common) Set(key string, d *Data) {
c.lock.Lock()
defer c.lock.Unlock()
c.data[key] = *d
}
The rest is basically the same, except instead of accessing the data through the receiver's fields directly, you'd access them through the getters and setters. In a webserver where most of the data is being read, you will probably want an RWMutex, so that reads can be executed concurrently with one another. Another advantage of the second approach is that you've encapsulated the data, so you can add in transparent writes to and/or reads from a memcache or a groupcache or something of that nature in the future if your application grows such a need.
One thing that I really like about defining my handlers as methods on an object is that it makes it much easier to unit test them: you can easily define a table driven test that includes the values you want and the output you expect without having to muck around with global variables.
Don't indulge in premature optimization. Define a Go package API to encapsulate the data and then you can change the implementation at any time. For example, just scribbling,
package data
type Key struct {
// . . .
}
type Data struct {
// . . .
}
var dataMap map[Key]Data
func init() {
dataMap = make(map[Key]Data)
}
func GetData(key Key) (*Data, error) {
data := dataMap[key]
return &data, nil
}