Passing a URL as URL param - go

I have this route that was written with route params
/properties/configurations/:name/:value
and when I call with with a URL as value like that
/properties/configurations/app.url/http://test.test
it doesn't hit my Revel controller I guess because the slash confuses it. I tried when calling the Javascript request with encodeURIComponent() so it removes the slashes and other chars that are problematic but it still doesn't hit the controller and gives 404.
The problem is it is used in a public API and I cannot change it to pass this data in the body instead so I'm trying to figure out how can I make revel recognize the pattern and correctly put the values inside {name} and {value}

You just need to use one of the escape functions:
package main
import "net/url"
func main() {
s := "http://test.test"
{
t := url.PathEscape(s)
println(t == "http:%2F%2Ftest.test")
}
{
t := url.QueryEscape(s)
println(t == "http%3A%2F%2Ftest.test")
}
}
https://golang.org/pkg/net/url#PathEscape
https://golang.org/pkg/net/url#QueryEscape

If you're able to pass the URL encoded URL to your Golang server as a path variable, you can run it through url.PathUnescape(str).
If the problem is that your router isn't reaching the correct handlers because the characters in your path variable aren't matching correctly, it's possible that you've incorrectly defined that path matcher. I don't have experience with revel, but with mux (github.com/gorilla/mux) I would expect it to look like the following:
package main
import (
"net/http"
"net/url"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/properties/configurations/app.url/{nestedURL:.*}", myHandler)
http.ListenAndServe(":8080", r)
}
func myHandler(w http.ResponseWriter, r *http.Request){
nestedURL := mux.Vars(r)["nestedURL"]
unescapedPath, err := url.PathUnescape(nestedURL)
if err != nil {
// handle err
}
}
The above example might even work without requiring you to URL encode the nested URL (but I really do suggest you URL encode it).

Related

How to use http.Get request inside handler func

How to make http.Get request inside of handler func?
For example, this simple code "should" return blank page in localhost:8080 browser but it go nuts. What I have missed in school?
package main
import "net/http"
func index(w http.ResponseWriter, r *http.Request) {
_, err := http.Get("www.google.com")
if err != nil {
panic(err)
}
}
func main() {
http.HandleFunc("/", index)
http.ListenAndServe(":8080", nil)
}
The problem is that you should use a protocol (e.g. https://) in the Get function:
_, err := http.Get("https://www.google.com")
The error in you original code is Get www.google.com: unsupported protocol scheme "".
http.Get() expects a URL, and www.google.com is not a URL; a URL begins with a scheme. Even though it is common to type "www.google.com" into a browser, it's still not a full URL; friendly browsers automatically prepend "http://" or "https://" before issuing the request. http.Get() isn't going to do that; it expects a well-formed URL to begin with.

Serving static content with GoLang Webserver

I'm exploring the depths of Go, and I've been trying to write a simple web application to wrap my head around everything. I'm trying to serve a React.js application.
Below is the code of the Go server. I've got the default route of / serving the index.html which is working fine. I'm struggling to allow static files to be served to that index file. I'm allowing the React App to do it's own client side routing, although I need to statically serve the JavaScript / CSS / Media files.
For example, I need to be able to serve the bundle.js file into the index.html for the React application to run. Currently, when I route to localhost:8000/dist/ I see the files being listed, but every file/folder that I click from there is throwing a 404 Page Not Found. Is there something that I'm missing? A push in the right direction would be greatly appreciated.
Webserver.go
package main
import (
"net/http"
"log"
"fmt"
"os"
"github.com/BurntSushi/toml"
"github.com/gorilla/mux"
)
type ServerConfig struct {
Environment string
Host string
HttpPort int
HttpsPort int
ServerRoot string
StaticDirectories []string
}
func ConfigureServer () ServerConfig {
_, err := os.Stat("env.toml")
if err != nil {
log.Fatal("Config file is missing: env.toml")
}
var config ServerConfig
if _, err := toml.DecodeFile("env.toml", &config); err != nil {
log.Fatal(err)
}
return config
}
func IndexHandler (w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./src/index.html")
}
func main () {
Config := ConfigureServer()
router := mux.NewRouter()
// Configuring static content to be served.
router.Handle("/dist/", http.StripPrefix("/dist/", http.FileServer(http.Dir("dist"))))
// Routing to the Client-Side Application.
router.HandleFunc("/", IndexHandler).Methods("GET")
log.Printf(fmt.Sprintf("Starting HTTP Server on Host %s:%d.", Config.Host, Config.HttpPort))
if err := http.ListenAndServe(fmt.Sprintf("%s:%d", Config.Host, Config.HttpPort), router); err != nil {
log.Fatal(err)
}
}
Per the gorilla mux docs, the proper way to do this would be a handler registered with PathPrefix, like this:
router.PathPrefix("/dist/").Handler(http.StripPrefix("/dist/", http.FileServer(http.Dir("dist"))))
An example can be found if you search the docs for something like PathPrefix("/static/").
This wildcard behavior actually comes by default with the pattern matching mechanism in net/http, so if you weren't using gorilla, but just the default net/http, you could do the following:
http.Handle("/dist/", http.StripPrefix("/dist/", http.FileServer(http.Dir("dist"))))
There could be an issue with file access path. Try:
// Strip away "/dist" instead of "/dist/"
router.Handle("/dist/", http.StripPrefix("/dist", http.FileServer(http.Dir("dist"))))

How to pass a url containing slashes as a path parameter in GO?

I want to send an url such as "Documents/folder1/folder2/file.txt" or it can have less slashes such as "Documents/folder1/file.txt", and I want to pass this url as a path parameter, such as router.HandleFunc("/myproject/v1/image/{url}", GetImage)
but when doing this it treats to go to the url for ex: /myproject/v1/image/Documents/folder1/file.txt and it does not find it so it returns 404.
I am using gorilla mux:
func main(){
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/myproject/v1/image/{url}", GetImage)
}
I thought that it was from the strictslash but when I set it false I remain getting 404
StrictSlashes has to do with a single trailing slash, not with whether or not slashes are matched inside of a parameter (they aren't). You need to use PathPrefix:
const (
imagesPrefix = "/myproject/v1/image/" // note no {url}
)
func main() {
router := mux.NewRouter()
router.PathPrefix(imagesPrefix).Handler(
http.StripPrefix(imagesPrefix, GetHandler),
)
}
func GetImage (w http.ResponseWriter, r *http.Request) {
// r.URL.Path should contain the image path.
}

Gorilla/mux: Image not displaying

I am new in Golang. I need display an image. I tried using Gorilla/mux.
But I am still getting Error:404. I thing may be the place where I used mux code is not correct.
Main func
package main
import (
"net/http"
"mytestsite/handlers"
"log"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/register", handlers.RegisterHandler)
r.HandleFunc("/sucess", handlers.Sucess)
r.HandleFunc("/login", handlers.Login)
r.HandleFunc("/list", handlers.ViewList)
r.HandleFunc("/logout", handlers.Logout)
r.HandleFunc("/edit", handlers.Edit)
r.HandleFunc("/EditnList", handlers.EditnList)
r.HandleFunc("/notvalid", handlers.NotValid)
r.HandleFunc("/delete", handlers.Delete)
r.HandleFunc("/listchoose", handlers.ListChoose)
r.HandleFunc("/email", handlers.SendEmail)
images := http.StripPrefix("/images/", http.FileServer(http.Dir("./frontend/images/")))
r.PathPrefix("/images/").Handler(images)
if err := http.ListenAndServe(":8181", r); err != nil {
log.Fatal("http.ListenAndServe: ", err)
}
}
Func which pass data to html
func ViewList(w http.ResponseWriter, r *http.Request) {
viewModel:=viewmodels.RegisterViewModel{}
user:=models.User{}
dbResults := user.ViewDB()
//Cookies below
cookieCheck := getCookie(r)
if (cookieCheck != ""){
err:=GetTemplate("list").Execute(w,dbResults)
if err!=nil{
panic(err)
}
} else {
viewModel.ErrorMessage="Please Enter Email Id and Password.."
err:=GetTemplate("login").Execute(w,viewModel)
if err!=nil{
panic(err)
}
}
}
Usage in html file
<td><img src="{{.Photo}}" alt="{{.Photo}}" style="width:50px;height:50px;"/></td>
Value of {{.Photo}} is stored to Db by following code:
ctime := time.Now()
uploadedfile := "frontend/images"+ctime.Format("20060102150405")+".jpg"
out, err := os.Create(uploadedfile)
SO value of {{.Photo}} will be like as follows
frontend/images/20160202171411.jpg
You are mixing two routers here.
First off, the http package has a package global default handler called: DefaultServeMux. This is an instance of http.ServeMux
When you call http.HandleFunc, DefaultServeMux is where that handler gets registered (source)
When you call http.ListenAndServe, the second parameter is what handler to use for HTTP requests that come in on your specified port.
If you pass nil as the handler (like you do in your code), you are telling the http server to use http.DefaultServeMux
Gorilla mux is an alternative to http.ServeMux. In general, you use one or the other.
In your case, you are registering your file server with a gorilla mux, but then telling http.ListenAndServe to use http.DefaultServeMux (by omitting the handler).
You can either register your file serve with the standard http library's default mux (via: http.Handle) or change your function mappings to register with your Gorilla mux (via: r.HandlerFunc).
If you choose to use Gorilla (more flexible solution, but is not really necessary given your example code), then pass that instead of nil to ListenAndServe.

Is it possible to know what route is used in HandleFunc

I am using http.HandleFunc("/resource", resource.Handle) from the package net/http and I was wondering if there was a way to see what route (in this case /resource) is used to get you to resource.Handle? Or do I have to create a Mux for this?
I'd like to know this to extract the resource from the url path to do some magic with it...
Yes you can
The main points to do:
Use the DefaultServeMux used by the HandleFunc method.
Construct a fake http.Request
For Example:
package main
import (
"fmt"
"net/http"
"net/url"
)
func main() {
theUrl, err := url.Parse("/response")
if err != nil {
fmt.Println(err.Error())
return
}
http.HandleFunc("/response", func(w http.ResponseWriter, r *http.Request) {
})
handler, path := http.DefaultServeMux.Handler(&http.Request{Method: "GET", URL: theUrl})
fmt.Println(handler, path)
}
see this Go Playground
http://golang.org/pkg/net/http/#Request
Use request.URL.Path to get the path used to access the handler.

Resources