I got something running with the Goji framework:
package main
import (
"fmt"
"net/http"
"github.com/zenazn/goji"
"github.com/zenazn/goji/web"
)
func hello(c web.C, w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", c.URLParams["name"])
}
func main() {
goji.Get("/hello/:name", hello)
goji.Serve()
}
What I was hoping someone could help me do is figure out how when an HTML form is submitted to send that data to Golang code.
So if there is an input field with the name attribute and the value of that is name and the user types a name in there and submits, then on the form submitted page the Golang code will print hello, name.
Here is what I could come up with:
package main
import(
"fmt"
"net/http"
"github.com/zenazn/goji"
"github.com/zenazn/goji/web"
)
func hello(c web.C, w http.ResponseWriter, r *http.Request){
name := r.PostFormValue("name")
fmt.Fprintf(w, "Hello, %s!", name)
}
func main(){
goji.Handle("/hello/", hello)
goji.Serve()
}
and here is my hello.html file:
in the body:
<form action="" method="get">
<input type="text" name="name" />
</form>
How do I connect hello.html to hello.go so that the Golang code gets what is in the input and returns hello, name in the form submitted page?
I'd greatly appreciate any and all help!
In order to read html form values you have to first call r.ParseForm(). The you can get at the form values.
So this code:
func hello(c web.C, w http.ResponseWriter, r *http.Request){
name := r.PostFormValue("name")
fmt.Fprintf(w, "Hello, %s!", name)
}
Should be this:
func hello(c web.C, w http.ResponseWriter, r *http.Request){
//Call to ParseForm makes form fields available.
err := r.ParseForm()
if err != nil {
// Handle error here via logging and then return
}
name := r.PostFormValue("name")
fmt.Fprintf(w, "Hello, %s!", name)
}
Edit: I should note that this was a point that tripped me up when learning the net/http package
Your form input name, name is the key to be fetched by go program.
<form action="" method="get">
<input type="text" name="name" />
</form>
You can use FormValue
https://golang.org/pkg/net/http/#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.
func hello(c web.C, w http.ResponseWriter, r *http.Request){
name := r.FormValue("name")
fmt.Fprintf(w, "Hello, %s!", name)
}
If FormFile doesn't works, better use ParseMultiForm
https://golang.org/pkg/net/http/#Request.ParseMultipartForm
You can use ParseMultipartForm
ParseMultipartForm parses a request body as multipart/form-data. The
whole request body is parsed and up to a total of maxMemory bytes of
its file parts are stored in memory, with the remainder stored on disk
in temporary files. ParseMultipartForm calls ParseForm if necessary.
After one call to ParseMultipartForm, subsequent calls have no effect
func hello(c web.C, w http.ResponseWriter, r *http.Request){
name := r.FormValue("name")
r.ParseMultipartForm(32 << 20)
fmt.Fprintf(w, "Hello, %s!", name)
}
Also, a form is useless unless some kind of processing takes place after the form is submitted. So use it accordingly.
Related
With a single API resource /, we have written only one handler that process GET & POST request on API resource /
POST we use to create a resource in database, byt sending data in request body
PUT we use to update an existing resource in database
My understanding is, RESTful best practice says, a handler need to serve an API resource(say /) for all requests GET, POST & PUT
We want the same handler to process PUT request, but the API resource will be something like /1234, where 1234 is existing id
Technically, API resource /1234 will also map to same handler that processes /, but,
From RESTful best practices, Does /1234 need to be handled without passing id as part of API resource URI? something like below...
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet { // for API resource '/'
p.getProducts(w, r)
return
}
if r.Method == http.MethodPost { // for API resource '/'
p.addProduct(w, r)
return
}
if r.Method == http.MethodPut { // for API resource '/'
p.updateProduct(w, r)
return
}
}
func updateProduct(w http.ResponseWriter, r *http.Request) {
var idString string
decoder := json.NewDecoder(r.Body)
decoder.Decode(idString)
id, err := findID(idString)
// do whatever with id
}
func findID(str string) (int, error) {
dfa := regexp.MustCompile(`/([0-9]+)`)
matches := dfa.FindAllStringSubmatch(str, -1) // returns [][]string
idString := matches[0][1]
id, err := strconv.Atoi(idString)
return id, nil
}
As I understood right you right.
You have two call which can be handle without Id for end point /.
One is POST when the back-end with generate you Id as a result.
Second is GET for all resources but this is up to you. Maybe because of secure reason you would not like to list all available resources.
One extra information is that PUT & 'POST' can use the same handler but logic in handler has to check if 'id' is provided and do extra more logic to create resource.
I currently have my routes set for my REST API as:
using mux
localhost:8080/user/{id}
localhost:8080/space/{id}
server.Router.HandleFunc("/users", middlewares.SetMiddlewareJSON(server.GetUsers)).Methods("GET")
server.Router.HandleFunc("/posts", middlewares.SetMiddlewareJSON(server.GetPosts)).Methods("GET")
the set middleware function
func SetMiddlewareJSON(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
next(w, r)
}
}
How would I combine them to become
localhost:8080/user/1/post/{id}
the repository for the project is here:
https://github.com/Robbie-Thomas/fullstack
You will need a HandlerFunc with that path:
server.Router.HandleFunc("/users/{userId}/post/{id}", middlewares.SetMiddlewareJSON(server.GetUsers)).Methods("GET")
In the handler func, you'll access those variables:
vars:=mux.Vars(request)
userId:=vars["userId"]
postId:=vars["id"]
I am using auth0 and golang for a rest service that is similar implemented as shown here.
I wonder how I can find out the name of the user that is currently triggering a certain API call - for instance if someone requests http://localhost:3000/products - the go handler in this case looks like this:
var ProductsHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
payload, _ := json.Marshal(products)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(payload))
})
Does the request r contain more information about the current user?
Or do I need to find out the current user in the middleware authentication:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
secret := []byte("{YOUR-AUTH0-API-SECRET}")
secretProvider := auth0.NewKeyProvider(secret)
audience := "{YOUR-AUTH0-API-AUDIENCE}"
configuration := auth0.NewConfiguration(secretProvider, audience, "https://{YOUR-AUTH0-DOMAIN}.auth0.com/", jose.HS256)
validator := auth0.NewValidator(configuration)
token, err := validator.ValidateRequest(r)
if err != nil {
fmt.Println(err)
fmt.Println("Token is not valid:", token)
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Unauthorized"))
} else {
next.ServeHTTP(w, r)
}
})
}
Does the token contain more information about the user?
I am a bit lost here. auth0 works perfectly to ensure that only registered persons can use the REST-API, but I want to deliver user specific information. So it depends on the current user what a REST call is handing back. Initially, I was thinking that auth0 would take care of this. Is there a simple way to achieve this?
Yes, you need to use token to get information about request issue.
To sort all you want you need to take a look to next:
Check out how token extracted in this method: token extraction
And the Claims here: Claims structure
And how combine it here: retrieve Claims
The claims have a field
Issuer string `json:"iss,omitempty"`
you are interested in.
In Golang, how do I serve static content out of the root directory while still having a root directory handler for serving the homepage.
Use the following simple web server as an example:
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", HomeHandler) // homepage
http.ListenAndServe(":8080", nil)
}
func HomeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "HomeHandler")
}
If I do
http.Handle("/", http.FileServer(http.Dir("./")))
I receive a panic saying that I have two registrations for "/". Every Golang example I've found on the internet suggests serving their static content out of different directories, but that doesn't help much for things like sitemap.xml, favicon.ico, robots.txt and other files which are by-practice or mandated to always be served out of the root.
The behavior I seek is the behavior which is found in most web servers such as Apache, Nginx, or IIS, where it first traverses your rules, and if no rule is found it looks for an actual file, and if no file is found it 404s. My guess is that instead of writing a http.HandlerFunc, I need to write a http.Handler which checks if I am referencing a file with an extension, and if so checks for file existence and serves the file, otherwise it 404s or serves the homepage is the request was for "/". Unfortunately I'm not certain how to even begin such a task.
Part of me says I'm massively over-complicating the situation which makes me think that I am missing something? Any guidance would be appreciated.
An alternative (not using ServeMux) solution is to serve explicitly each file located in the root directory. The idea behind is to keep the number of root-based files very small.
sitemap.xml, favicon.ico, robots.txt are indeed mandated to be served out of the root :
package main
import (
"fmt"
"net/http"
)
func HomeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "HomeHandler")
}
func serveSingle(pattern string, filename string) {
http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filename)
})
}
func main() {
http.HandleFunc("/", HomeHandler) // homepage
// Mandatory root-based resources
serveSingle("/sitemap.xml", "./sitemap.xml")
serveSingle("/favicon.ico", "./favicon.ico")
serveSingle("/robots.txt", "./robots.txt")
// Normal resources
http.Handle("/static", http.FileServer(http.Dir("./static/")))
http.ListenAndServe(":8080", nil)
}
Please move all other resources (CSS, JS, etc.) to a proper subdirectory, e.g. /static/ .
One thing I thought of that might help you is that you can create your own ServeMux. I added to your example so that chttp is a ServeMux that you can have serve static files. The HomeHandler then checks to see if it should serve a file or not. I just check for a "." but you could do a lot of things. Just an idea, might not be what you are looking for.
package main
import (
"fmt"
"net/http"
"strings"
)
var chttp = http.NewServeMux()
func main() {
chttp.Handle("/", http.FileServer(http.Dir("./")))
http.HandleFunc("/", HomeHandler) // homepage
http.ListenAndServe(":8080", nil)
}
func HomeHandler(w http.ResponseWriter, r *http.Request) {
if (strings.Contains(r.URL.Path, ".")) {
chttp.ServeHTTP(w, r)
} else {
fmt.Fprintf(w, "HomeHandler")
}
}
Using Gorilla mux package :
r := mux.NewRouter()
//put your regular handlers here
//then comes root handler
r.HandleFunc("/", homePageHandler)
//if a path not found until now, e.g. "/image/tiny.png"
//this will look at "./public/image/tiny.png" at filesystem
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./public/")))
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
Are there any packages to support SOAP/WSDL on Go?
There isn't support for WSDL in Go. Support in other languages are either static or dynamic: Either structs are pre-generated from the WSDL, or it's done on the fly with hash tables.
You can, however, encode and decode SOAP requests manually. I found that the standard encoding/xml package to be insufficient for SOAP. There are so many quirks in different servers, and the limitations in encoding/xml make it difficult generate a request these servers are happy with.
For example, some servers need xsi:type="xsd:string" on every string tag. In order to do this properly your struct needs to look like this for encoding/xml:
type MethodCall struct {
One XSI
Two XSI
}
type XSI struct {
Type string `xml:"xsi:type,attr"`
Vaue string `xml:",chardata"`
}
And you construct it like this:
MethodCall{
XSI{"xsd:string", "One"},
XSI{"xsd:string", "Two"},
}
Which gives you:
<MethodCall>
<One xsi:type="xsd:string">One</One>
<Two xsi:type="xsd:string">Two</Two>
</MethodCall>
Now this might be ok. It certainly gets the job done. But what if you needed more than just a string? encoding/xml currently doesn't support interface{}.
As you can see this gets complicated. If you had one SOAP API to integrate, this probably wouldn't be too bad. What if you had several, each with their own quirks?
Wouldn't it be nice if you could just do this?
type MethodCall struct {
One string
Two string
}
Then say to encoding/xml: "This server want xsi types".
To solve this problem I created github.com/webconnex/xmlutil. It's a work in progress. It doesn't have all the features of encoding/xml's encoder/decoder, but it has what is needed for SOAP.
Here's a working example:
package main
import (
"bytes"
"encoding/xml"
"fmt"
"github.com/webconnex/xmlutil"
"log"
//"net/http"
)
type Envelope struct {
Body `xml:"soap:"`
}
type Body struct {
Msg interface{}
}
type MethodCall struct {
One string
Two string
}
type MethodCallResponse struct {
Three string
}
func main() {
x := xmlutil.NewXmlUtil()
x.RegisterNamespace("http://www.w3.org/2001/XMLSchema-instance", "xsi")
x.RegisterNamespace("http://www.w3.org/2001/XMLSchema", "xsd")
x.RegisterNamespace("http://www.w3.org/2003/05/soap-envelope", "soap")
x.RegisterTypeMore(Envelope{}, xml.Name{"http://www.w3.org/2003/05/soap-envelope", ""},
[]xml.Attr{
xml.Attr{xml.Name{"xmlns", "xsi"}, "http://www.w3.org/2001/XMLSchema-instance"},
xml.Attr{xml.Name{"xmlns", "xsd"}, "http://www.w3.org/2001/XMLSchema"},
xml.Attr{xml.Name{"xmlns", "soap"}, "http://www.w3.org/2003/05/soap-envelope"},
})
x.RegisterTypeMore("", xml.Name{}, []xml.Attr{
xml.Attr{xml.Name{"http://www.w3.org/2001/XMLSchema-instance", "type"}, "xsd:string"},
})
buf := new(bytes.Buffer)
buf.WriteString(`<?xml version="1.0" encoding="utf-8"?>`)
buf.WriteByte('\n')
enc := x.NewEncoder(buf)
env := &Envelope{Body{MethodCall{
One: "one",
Two: "two",
}}}
if err := enc.Encode(env); err != nil {
log.Fatal(err)
}
// Print request
bs := buf.Bytes()
bs = bytes.Replace(bs, []byte{'>', '<'}, []byte{'>', '\n', '<'}, -1)
fmt.Printf("%s\n\n", bs)
/*
// Send response, SOAP 1.2, fill in url, namespace, and action
var r *http.Response
if r, err = http.Post(url, "application/soap+xml; charset=utf-8; action="+namespace+"/"+action, buf); err != nil {
return
}
dec := x.NewDecoder(r.Body)
*/
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
<soap:Body>
<MethodCallResponse>
<Three>three</Three>
</MethodCallResponse>
</soap:Body>
</soap:Envelope>`))
find := []xml.Name{
xml.Name{"", "MethodCallResponse"},
xml.Name{"http://www.w3.org/2003/05/soap-envelope", "Fault"},
}
var start *xml.StartElement
var err error
if start, err = dec.Find(find); err != nil {
log.Fatal(err)
}
if start.Name.Local == "Fault" {
log.Fatal("Fault!") // Here you can decode a Soap Fault
}
var resp MethodCallResponse
if err := dec.DecodeElement(&resp, start); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)
}
With the above example I use the Find method to get the response object, or a Fault. This isn't strictly necessary. You can also do it like this:
x.RegisterType(MethodCallResponse{})
...
// Decode response
dec := x.NewDecoder(bytes.NewBufferString(`<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
<soap:Body>
<MethodCallResponse>
<Three>three</Three>
</MethodCallResponse>
</soap:Body>
</soap:Envelope>`))
var start *xml.StartElement
var resp Envelope
if err := dec.DecodeElement(&resp, start); err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n\n", resp)
You'll find the Find method useful when your data looks like this:
<soap:Envelope>
<soap:Body>
<MethodResponse>
<MethodResult>
<diffgr:diffgram>
<NewDataSet>
<Table1 diffgr:id="Table1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
<Three>three</Three>
</Table1>
</NewDataSet>
</diffgr:diffgram>
</MethodResult>
</MethodResponse>
</soap:Body>
</soap:Envelope>
This is a DiffGram, part of Microsoft .NET. You can use the Find method to get to Table1. The Decode and DecodeElement method also works on slices. So you can pass in a []MethodCallResponse if NewDataSet happens to contain more than one result.
I do agree with Zippower that SOAP does suck. But unfortunately a lot of enterprises use SOAP, and you're sometimes forced to use these APIs. With the xmlutil package I hope to make it a little less painful to work with.
Nope.
SOAP sucks, but I had to implement a server of an already-defined protocol that uses SOAP, so I listened with net/http and decoded/encoded envelopes with encoding/xml. In few minutes, I already served my first envelope with Go.
While there's still nothing in Go itself, there is gowsdl. So far, it seems to work well enough for me to interface with several SOAP services.
I don't use the SOAP proxy it provides, which I believe doesn't support auth, but gowsdl generates the structs and code I need from the WSDL to marshal requests and unmarshal responses--a big win.
one option is to use gsoap which produces a C WSDL client
and then use that client through GO with cgo