Gorilla Session not setting cookie - go

here is the code for my go server, I have no idea why my gorilla session isn't working. it seems like everything works up to session.save(r, w). I already checked my cookies using the chrome dev tools and no matter what I do I can't get a cookie to appear. I know that my authentication is bad already I just need help with getting sessions working which is my goal. I don't know why this function isn't working can anybody help?
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/context"
"github.com/gorilla/sessions"
)
var store = sessions.NewCookieStore([]byte("super-secret"))
func loginAuthHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.FormValue("username")
password := r.FormValue("password")
fmt.Println("username:", username, "password:", password)
if password == "welcome" && username == "guest" {
fmt.Fprintf(w, "You logged in Succesfully!")
session, _ := store.Get(r, "session")
session.Values["authenticated"] = true
session.Save(r, w)
fmt.Println("session started!")
fmt.Println(session)
} else {
fmt.Fprintf(w, "Wrong Login!")
}
}
func secret(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
fmt.Println(session.Values["authenticated"])
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
fmt.Fprintf(w, "The cake is a lie!")
}
func main() {
store.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8,
HttpOnly: true,
}
http.HandleFunc("/secret", secret)
http.HandleFunc("/loginauth", loginAuthHandler)
http.Handle("/", http.FileServer(http.Dir("public")))
log.Fatal(http.ListenAndServe(":3002", context.ClearHandler(http.DefaultServeMux)))
}
Here is my index.html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Go Web App" />
<link rel="stylesheet" href="index.css">
<title>Login Form</title>
</head>
<body>
<div class="container">
<h1> Login Form </h1>
<p> user: guest | pass: welcome</p> <br>
<form action="/loginauth" method="POST">
<label for="username">Name:</label><br>
<input type="text" id="username" name="username"> <br>
<label for="password">Password:</label> <br>
<input type="password" id="password" name="password"> <br>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>

As per the docs for session.Save
Save is a convenience method to save this session. It is the same as calling store.Save(request, response, session). You should call Save before writing to the response or returning from the handler.
In your code you are writing to the response (fmt.Fprintf(w, "You logged in Succesfully!")) before calling session.Save. This means that the response (including the headers that contain cookies) is written before the cookie gets set (so the cookies are not sent to the client).
To fix this just move fmt.Fprintf(w, "You logged in Succesfully!") underneath the call to session.Save.

Related

Why does this request not POST?

There are many similar questions implemented in different stacks, but I have not found a useful answer. This code is modeled on many different tutorials, here is one: https://divyanshushekhar.com/golang-forms-data-request-body/
Pressing the button is supposed to submit the form so that the value of dataRequest can be used, however, it does not appear to post. Why?
<!DOCTYPE html>
<meta charset="utf-8" http-equiv="Content-Security-Policy" content="img-src * 'self' data: https:">
<head>
<title>Demo</title>
<link rel="icon" type="image/png" href="./favicon.ico">
</head>
<body style="background-color:#F0F8FF" style="font-size: 18px; font-family:verdana,arial,tahoma,serif;">
<form name="demoForm" style="background-color:#92a8d1">
<fieldset>
<input id="dataRequest" type="request" method="POST" value=""/>
<button type="submit" value="Run" />
</fieldset>
</form>
</body>
</html>
package main
import (
"fmt"
"net/http"
"log"
)
func index() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
http.ServeFile(w, r, "visible/index.html")
return
case "POST":
fmt.Println("Posted a request!")
err := r.ParseForm();
if err != nil {
log.Fatal(err)
}
request := r.Form.Get("dataRequest")
fmt.Println(request)
return
}
})
}
func main() {
mux := http.NewServeMux()
mux.Handle("/", index())
http.ListenAndServeTLS(":443", "./server.crt", "./server.key", mux)
}

Does gin-gonic support get request?

I am new in gin-gonic framework and i have been trying to read the values from the inputs that i added in a get request from html but i have not been able to read the values that i wrote.
When i submit the request the browser sends this url :
http://localhost:3000/backend?name1=value1&name2=value2&name3=value3
I have been looking in the internet where gin-gonic uses this url type but i have only found that it uses url like this one
http://localhost:3000/backend/value1
html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form method="GET" action="/backend">
<input id="store" name="name1" type="text">
<input id="razon" name="name2" type="text">
<input id="total" name="name3" type="text">
<input type="submit" value="submit">
</form>
</body>
</html>
golang code:
package main
import(
"net/http"
"fmt"
"github.com/gin-gonic/contrib/static"
"github.com/gin-gonic/gin"
)
func main(){
router := gin.Default()
router.Use(static.Serve("/",static.LocalFile("./views",true)))
router.GET("/backend",func(c *gin.Context){
fmt.Println(c.Param("name1"))
c.JSON(http.StatusOK, gin.H{
"name1" : c.Param("name1"),
})
})
router.Run(":3000")
}
Actual result:
{"name1":""}
Expected result:
{"name1":"value1"}
The function you are looking for is not Param(), it's Query().
https://github.com/gin-gonic/gin#querystring-parameters

Form Always Empty

I've been building a Go todo list and I'm trying to add the ability to add new items, but every time I access the form value, it comes out empty. Here's the handler I built:
func addHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
fmt.Print(err)
}
cook, _ := r.Cookie("userid")
id := cook.Value
r.ParseForm()
text := r.FormValue("todo")
addTodo(text,id) //inserts into database
http.Redirect(w,r,"/todo",http.StatusFound)
}
And here's the html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
{{range .}}
<tr><td>{{printf "%s" .Text}}</td><td>delete</td></tr>
{{end}}
</table>
<form action="/add" method="post"><input type="text" name="todo"><button type="submit">Add</button></form>
</body>
</html>

Golang template does not render html

I created a subfolder called 'views' in my web root directory. Within the View folder, I have the static folder which contains the css and js files.
The html pages are rendered when I have the html files in the web root. However they do not render when placed within the views folder. I am using template.ParseGlob to parse the file and ExecuteTemplate to render.
package main
import (
"html/template"
"net/http"
"github.com/gorilla/mux"
)
var router = mux.NewRouter()
var tmpl *template.Template
func init() {
tmpl = template.Must(template.ParseGlob("view/*.html"))
}
func indexPage(w http.ResponseWriter, r *http.Request) {
err := tmpl.ExecuteTemplate(w, "signin", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
router.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir("view/"))))
router.HandleFunc("/", indexPage)
http.ListenAndServe(":8091", router)
}
HTML files: Have defined the header and footer in index.html which I refernce in the signin.html file
{{ define "header"}}
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>User Sign in</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/static/css/main.css">
<script src="/static/js/vendor/modernizr-2.8.3-respond-1.4.2.min.js"></script>
</head>
<body>
{{end}}
{{define "footer"}}
<footer class="panel-footer"><p>© Company 2016</p></footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
<script src="/static/js/vendor/bootstrap.min.js"></script>
<script src="/static/js/main.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','UA-XXXXX-X','auto');ga('send','pageview');
</script>
</body>
</html>
{{end}}
signin.html file:
{{define "signin"}}
{{template "header" .}}
<h1 class="alert alert-info">Login</h1>
<div class="container">
{{with .Errors.message}}
<div class="alert alert-danger">
{{.}}
</div>
{{end}}
<form method="POST" action="/">
<label class="form-control" for="uname">User Name</label>
<input class="form-control" type="text" id="uname" name="uname">
<label class="form-control" for="password">Password</label>
<input class="form-control" type="password" id="password" name="password">
<button class="btn btn-info" type="submit">Submit</button>
</form>
{{template "footer" .}}
{{end}}
Why is it that this doesn't work when I place the html files in the sub-directory 'views'. The only thing that changes is the argument to parseGlob.
I believe all you need to do is remove this line:
router.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir("view/"))))
Works for me. Though you need to clean up your html a bit too - I see at least a missing </div>.
Templates are processed on the server and do not need to be served over internet. At the same time this route entry conflicts with the following one (indexPage) which defines another handler for the same route entry ("/"). So when you open it in a browser, server just send template files over internet. While indexPage handler is never called as directory handler is matched first.
Also you talking about "views" folder, but you code says "view" (without 's' at the end). Could be another simple reason.

Ajax Request not sending to Go web server

I am just starting with learning web development, Go, and Ajax but I am having trouble seeing what is going wrong. I am trying to simply send data back and forth between the client and the server. With the Ajax request, I am sending data from the form to the server but it does not seem to reach the server because the log doesn't print "in posthandler" which leads me to think something is wrong with the ajax request. Attached is the main.go, index.html, and js/getData.js with all the relevant code.
main.go
package main
import (
"fmt"
"net/http"
"io/ioutil"
"log"
)
var INDEX_HTML []byte
func main(){
fmt.Println("starting server on http://localhost:8888/\nvalue is %s", value)
http.HandleFunc("/", IndexHandler)
http.HandleFunc("/post", PostHandler)
http.ListenAndServe(":8888", nil)
}
func IndexHandler(w http.ResponseWriter, r *http.Request){
log.Println("GET /")
w.Write(INDEX_HTML)
}
func PostHandler(w http.ResponseWriter, r *http.Request){
r.ParseForm()
log.Println("in posthandler", r.Form)
var value = r.FormValue("textfield")
w.Write([]byte(value))
}
func init(){
INDEX_HTML, _ = ioutil.ReadFile("./html/index.html")
}
index.html
<!doctype html>
<html>
<head>
<title>Page Title</title>
<script src="js/getData.js"></script>
</head>
<body>
<form action="/post" method="post">
<textarea type="text" name="input" id="textfield"></textarea>
<br />
<input type="submit" name="button" id="button" value="Send" onclick="loadXMLDoc()"/>
</form>
<div id="fromserver">
</div>
</body>
</html>
js/getData.js
function loadXMLDoc() {
var xmlhttp;
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("fromserver").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST","post",true);
xmlhttp.send();
}
There are two things:
No handler present to render assest (in this case js/.)
Form by itself get submitted due to "submit" HTML element.
here is your updated code
main.go
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
var INDEX_HTML []byte
func main() {
fmt.Println("starting server on http://localhost:8888/\nvalue is %s", "asdf")
http.HandleFunc("/", IndexHandler)
http.HandleFunc("/post", PostHandler)
serveSingle("/js/getData.js", "./js/getData.js")
http.ListenAndServe(":8888", nil)
}
func serveSingle(pattern string, filename string) {
http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filename)
})
}
func IndexHandler(w http.ResponseWriter, r *http.Request) {
log.Println("GET /")
w.Write(INDEX_HTML)
}
func PostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
log.Println("in posthandler", r.Form)
var value = r.FormValue("textfield")
w.Write([]byte(value))
}
func init() {
INDEX_HTML, _ = ioutil.ReadFile("./html/index.html")
}
index.html
<!doctype html>
<html>
<head>
<title>Page Title</title>
<script src="js/getData.js"></script>
</head>
<body>
<form action="/post" method="post">
<textarea type="text" name="input" id="textfield"></textarea>
<br />
<input type="button" name="button" id="button" value="Send" onclick="loadXMLDoc()"/>
</form>
<div id="fromserver">
</div>
</body>
</html>

Resources