Ajax Request not sending to Go web server - ajax

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>

Related

Prevent overwriting of blocks with same name in Go Template

I'm having difficulty in rendering the correct content using templates in Go. Either case of navigating to /about or / the same content is getting rendered. Below is the current state of code.
I have read that you can parse templates in each handleFunc (for each request) but that seems to be an inefficient way to mitigate the issue.
Code
I have the following templates
base
header
footer
index
about
{{ define "base"}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Project Website</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css#2/out/water.css">
</head>
<body>
{{template "header" .}}
{{template "body" .}}
{{template "footer" .}}
</body>
</html>
{{end}}
{{define "header"}}
<h1>Header</h1>
{{end}}
{{define "footer"}}
<h1>Footer</h1>
{{end}}
{{template "base" .}}
{{define "body"}}
<h1>About</h1>
{{end}}
{{template "base" .}}
{{define "body"}}
<h1>Index</h1>
{{end}}
main.go
package main
import (
"html/template"
"log"
"net/http"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseGlob("templates/*"))
}
func main() {
// Connect to database.
// Routes
http.HandleFunc("/about", about)
http.HandleFunc("/", index)
http.HandleFunc("/favicon.ico", doNothing) // TODO Replace with something like do not found
// Listen and serve.
log.Fatal(http.ListenAndServe(":8000", nil))
}
// TODO go away
func doNothing(w http.ResponseWriter, r *http.Request) {}
handlerFunctions.go
package main
import (
"log"
"net/http"
)
func index(rw http.ResponseWriter, req *http.Request) {
log.Println("Index page called")
tpl.ExecuteTemplate(rw, "index.gohtml", nil)
}
func about(rw http.ResponseWriter, req *http.Request) {
log.Println("About page called")
tpl.ExecuteTemplate(rw, "about.gohtml", nil)
}

Gorilla Session not setting cookie

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.

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

How to render/show images in HTML created on the fly with Golang and gin-gonic

I'am generating QR codes and right after I need to show them in an HTML without saving them as images.
So far I can generate them but I have problems rendering them in the HTML
I have here the golang code that generates the QR and the HTML template that try to render them
golang
import (
"fmt"
"github.com/gin-gonic/gin"
qrcode "github.com/skip2/go-qrcode"
)
func renderQRExport(c *gin.Context){
var images [][]byte
var img []byte
var err error
for i := 0; i < 25; i++ {
img, err = qrcode.Encode("https://example.org", qrcode.Medium, 256)
images = append(images, img)
if err != nil {
fmt.Print(err)
}
}
render(c, gin.H{
"images": images,
}, "qr.html")
}
HTML Template
<!doctype html>
<html class="no-js" lang="">
<head>
<title>QR export</title>
{{template "imports.html"}}
</head>
<body>
<div class="margin-body-log-in-worker">
<div class="row">
{{range .images}}
<div class="col-4 col-sm-4 col-md-3 col-xl-2 center">
<img src="data:image/png;base64,{{.image}}" class="img-fluid image-dashboard" />
</div>
{{end}}
</div>
</div>
</body>
</html>
One of the things that I'am not able to do, as they say in this article:
https://www.sanarias.com/blog/1214PlayingwithimagesinHTTPresponseingolang
and also the Encode method itself says "To serve over HTTP, remember to send a Content-Type: image/png header."
How can I set properly the content type in the request using gingonic and how to decode properly in the HTML?
I solved my own question thanks to this article: https://www.socketloop.com/tutorials/golang-encode-image-to-base64-example
The proble is that i needed to Encode it to String with 'imgBase64Str := base64.StdEncoding.EncodeToString(buf)'
So the final code to work is as follows:
Golang
func renderQRExport(c *gin.Context){
var images []string
var img []byte
var err error
for i := 0; i < 25; i++ {
img, err = qrcode.Encode("https://example.org", qrcode.Medium, 256)
img2 := base64.StdEncoding.EncodeToString(img)
images = append(images, img2)
if err != nil {
fmt.Print(err)
}
}
render(c, gin.H{
"images": images,
}, "qr.html")
}
HTML
<!doctype html>
<html class="no-js" lang="">
<head>
<title>QR export</title>
{{template "imports.html"}}
</head>
<body>
<div class="margin-body-log-in-worker">
<div class="row">
{{range .images}}
<div class="col-4 col-sm-4 col-md-3 col-xl-2 center">
<img src="data:image/png;base64,{{.}}" class="img-fluid image-dashboard" />
</div>
{{end}}
</div>
</div>
</body>
</html>

How to render struct to html template?

i going to render html with data,when render,i don't know how to render struct of other file return for render on controller ,
code :
packages controller
type Index struct {
Title string
Body string
}
func IndexController(w http.ResponseWriter , r *http.Request){
if r.Method == "POST"{
data := &Index{
Title: "Hello",
Body: "Welcome to the WebGo.",
}
ff := renders.Sample{Temppath:"templates/index.tmpl",Data:data}
ff.Render(w)
my render package:
package renders
import (
"html/template"
"log"
"net/http"
)
type Sample struct {
Temppath string
Data struct{} ## i don't know how to use pass value of package controller to renders package ?
}
func (obj Sample) Render(w http.ResponseWriter) error {
var indexTemplate = template.Must(template.ParseFiles(obj.Temppath))
if err := indexTemplate.Execute(w, obj.Data); err != nil {
log.Println(err)
return err
}
return nil
}
html code :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="/static/js/sample.js"></script>
<title>{{.Title}}</title>
<style>
body {
font-family: sans-serif;
}
h1 {
background: #ddd;
}
#sidebar {
float: right;
}
</style>
</head>
<body>
<h1>{{.Title}}</h1>
<div id="sidebar">
{{block "sidebar" .}}
<ul>
</ul>
{{end}}
</div>
{{block "content" .}}
<div id="content">
{{.Body}}
</div>
{{end}}
</body>
</html>
how to pass type Index struct to renders package for use indexTemplate.Execute(w, obj.Data)
Declare field Data in struct Sample as interface{}:
type Sample struct {
Temppath string
Data interface{}
}
The type Sample then can also be used in other controllers as placeholder of any data which is going to be passed to template.

Resources