Gorilla/mux: Image not displaying - go

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.

Related

Passing a URL as URL param

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).

golang cgi + apache login session management

I am new to golang. I want to use golang as cgi for my apache server. I dont want to run my golang program as a listener/server. I write .go files for each action such as login.go, logout.go, welcome.go and compile them into individual exes. I rename the exes into cgi and put them in the cgi-bin folder of apache and post from my html file to cgi bin folder. I want my go lang to serve through apache.
This is my simple html form
<html>
<head><title>Go Test</title></head>
<body>
<form action='cgi-bin/login.cgi' method='post'>
username : <input name='username' value='vimal'><br>
password : <input name='password' value='hello'><br>
<input type='submit' value='submit'>
</form>
</body>
</html>
This is my golang source for login. I compile into login.exe rename it to login.cgi and put it in cgibin folder of apache.
package main
import (
"net/http/cgi"
"net/http"
"fmt"
)
var (
// key must be 16, 24 or 32 bytes long (AES-128, AES-192 or AES-256)
// key = []byte("super-secret-key")
key = uuid.NewV4().String()
store = sessions.NewCookieStore(key)
)
func errorResponse(code int, msg string) {
fmt.Printf("Status:%d %s\r\n", code, msg)
fmt.Printf("Content-Type: text/plain\r\n")
fmt.Printf("\r\n")
fmt.Printf("%s\r\n", msg)
}
func main() {
var req *http.Request
var w *http.ResponseWriter
var err error
req, err = cgi.Request()
if err != nil {
errorResponse(500, "cannot get cgi request" + err.Error())
return
}
if err := req.ParseForm(); err != nil {
errorResponse(500, "cannot get cgi request" + err.Error())
}
username := req.FormValue("username")
password := req.FormValue("password")
//create session
//store session variables like user id, user name etc., that can be accessed through other .cgi files like welcome.cgi
// Use req to handle request
fmt.Printf("Content-type: text/html\n\n")
fmt.Printf("<!DOCTYPE html>\n")
fmt.Printf("<p>username: %s\n",username)
fmt.Printf("<p>password: %s\n",password)
fmt.Printf("req=%v\r\n", req)
}
I need help to create a session and store session variables like user id, username etc.,
If my another golang cgi file welcome.cgi is called it should be able to access the session variables like user id, name and print them
Please provide me with complete code. I am new to golang.
I dont want to use my golang as server. I just want to make small cgi pages.
Thanks
You can use normal handlers like the ones used in several examples on the internet, that way you don't need to use a series of fmt.Printf to send data to the CGI server. One way that I found easy to work is by using the cgi.Serve function which can be used in conjunction with an http.HandlerFunc. Using http.HandlerFunc or http.Handler will allow you to use any session manager implementation in go that uses http.ResponseWriter and http.Request. Note however that you should not initialize your store with a randomly generated key from inside your program, and also, if you use a database back-end you will not be able to use connection polling directly from go, since your program main function will be executed on each request and it should open an close connections on each invocation.
Following is a simple example that uses the approach discussed above:
package main
import (
"encoding/hex"
"fmt"
"io"
"net/http"
"net/http/cgi"
"os"
"github.com/gorilla/sessions"
)
func main() {
// Use Serve function with an anonymous function, you can also use instances
// of http.Handler. The function does not need to be an anonymous function, it
// just has to match the HandlerFunc signature
err := cgi.Serve(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Get the session auth key from a trusted source,
// in this example an env var is used. You can use any mechanism you want
// so long that you don't generate it from within this program
key, _ := hex.DecodeString(os.Getenv("SESSION_AUTH_KEY"))
store := sessions.NewCookieStore(key)
// Get a session from the store if any
sess, err := store.Get(r, "mysess")
if err != nil {
io.WriteString(rw, fmt.Sprintf("error reading cookies: %v", err))
return
}
if sess.IsNew {
sess.Values["val"] = 1
//Save your store before writing anything to the client
if err := sess.Save(r, rw); err != nil {
io.WriteString(rw, "error writing sesion")
} else {
io.WriteString(rw, "new session")
}
return
}
//Write session values to validate that your session is working
io.WriteString(rw, "Values:")
for name, value := range sess.Values {
io.WriteString(rw, fmt.Sprintf("name: %s, val: %v", name, value))
}
}))
if err != nil {
fmt.Fprintf(os.Stderr, "Error :%v", err)
}
}

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"))))

Gorilla Mux router from inside handler only works once then gives 404 page not found

I'm using Gorilla mux as my router and I'm having a very strange behaviour. On the first request to the server, I get a valid response. But on subsequent requests, I receive a 404 page not found. There are no errors in the console.
My code is pretty straightforward (it can be copy-pasted to test it right out):
package main
import (
"fmt"
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
router := mux.NewRouter()
router.HandleFunc("/", RootHandler).Name("root")
http.Handle("/", router)
log.Println("Listening on port 1337...")
if err := http.ListenAndServe(":1337", nil); err != nil {
log.Fatal("http.ListenAndServe: ", err)
}
}
func RootHandler(w http.ResponseWriter, r *http.Request) {
content := "Welcome to "
rootUrl, err := mux.CurrentRoute(r).Subrouter().Get("root").URL()
if err != nil {
log.Printf("mux.CurrentRoute(r).Subrouter().Get(\"root\").URL(): ", err)
}
response := content + rootUrl.String()
fmt.Fprintf(w, response)
}
After some code commenting and tests, it seems the following line is the culprit:
rootUrl, err := mux.CurrentRoute(r).Subrouter().Get("root").URL()
This method of getting the router inside the handler using the current request comes from another StackOverflow post: How to call a route by its name from inside a handler?
But for a strange reason, it only works once:
shell-1$ go run servertest.go
2014/10/30 13:31:34 Listening on port 1337...
shell-2$ curl http://127.0.0.1:1337
Welcome to /
shell-2$ curl http://127.0.0.1:1337
404 page not found
As you can see, there are no errors in the console.
Does someone have an idea of why it only works once ?
The problem is Subrouter() isn't made to return the router, but to create one, thus it changes the matcher of the router it is called on, making you lose the handler.
You could try passing the router to the handler using closures instead.
func RootHandler(router *mux.Router) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
...
}
}
i run to this problem and fixe it by re initiating the methods
//create a subrouter separately \
subRoute := mux.CurrentRoute(req).Subrouter() \
//Call the Route u want and store the URL
url, err := subRoute.Get("check_authorization").URL("id", key, "password", token)
// re-initiate the method to GET or whatever u had before
subRoute.Methods(http.MethodGet)

Resources