The Template Handler data is not showing in the web - go

Guys I am making a create your own adventure type book in which the user has options to select events. I am taking the story data from a json file. I have created two files named story.go and main.go where story.go handles all the functions and main.go has only the server. Look at the following codes
story.go
package gyg
import (
"encoding/json"
"io"
"net/http"
"text/template"
)
var defaultHandlerTemplate = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Give Yourself Goosebumps</title>
</head>
<body>
<h1>{{.Title}}</h1>
{{range .Paragraphs}}
<p>{{.}}</p>
{{end}}
<ul>
{{range .Options}}
<li> {{.Text}} </li>
{{end}}
</ul>
</body>
</html>
`
var tpl *template.Template
type Story map[string]Chapter
type Chapter struct {
Title string `json:"title"`
Paragraphs []string `json:"story"`
Options []Option `json:"options"`
}
type Option struct {
Text string `json:"text"`
Arc string `json:"arc"`
}
type handler struct {
s Story
}
func init() {
tpl = template.Must(template.New("").Parse("defaultHandlerTemplate"))
}
func JsonStory(r io.Reader) (Story, error) {
d := json.NewDecoder(r)
var story Story
if err := d.Decode(&story); err != nil {
return nil, err
}
return story, nil
}
func NewHandler(s Story) http.Handler {
return handler{s}
}
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := tpl.Execute(w, h.s["intro"])
if err != nil {
panic(err)
}
}
main.go
package main
import (
"flag"
"fmt"
"go-projects/gyg"
"log"
"net/http"
"os"
)
func main() {
filename := flag.String("file", "gopher.json", "the file with GYG story.")
flag.Parse()
f, err := os.Open(*filename)
if err != nil {
panic(err)
}
story, err := gyg.JsonStory(f)
if err != nil {
panic(err)
}
server := http.Server{
Addr: "127.0.0.1:3000",
}
h := gyg.NewHandler(story)
fmt.Printf("Startin the server on port %s\n", server.Addr)
log.Fatal(http.ListenAndServe(server.Addr, h))
}
On running main.go the server is listening on port 3000 but when opening port 3000 on browser, it's displaying
defaultHandlerTemplate

Related

What is the problem in my code when connecting to a database and outputting it to html and then to a website?

I wrote code in golango to connect to the database on the server and output the contents of the tables to the website. I also wrote code for the html output of the table. There are no problems and it connects, but the error "404 page not found" lights up on the web page. What is this error and what is the reason? This is the first time I've seen this
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"html/template"
_ "log"
"net/http"
)
type Жанр struct {
idЖанр int
Название_жанра string
}
var database *sql.DB
func home_db(w http.ResponseWriter, r *http.Request) {
rows, err := database.Query("select * from newbd.Жанр")
if err != nil {
panic(err)
}
defer rows.Close()
ganr := []Жанр{}
for rows.Next() {
p := Жанр{}
err = rows.Scan(&p.idЖанр, &p.Название_жанра)
if err != nil {
panic(err)
continue
}
ganr = append(ganr, p)
}
tmpl, _ := template.ParseFiles("home.html")
tmpl.Execute(w, ganr)
}
func main() {
db, err := sql.Open("mysql", "xxxxx:xxxxxx#tcp(xx.xx.xxx.xxx:xx)/xxxxx")
if err != nil {
panic(err)
}
defer db.Close()
fmt.Println("OK")
http.HandleFunc("/dat/", home_db)
http.ListenAndServe(":8100", nil)
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RUMP</title>
</head>
<body>
<table>
<thead>
<th>idЖанр</th>
<th>Название_жанра</th>
</thead>
{{range . }}
<li>
<td>{{.idЖанр}}</td>
<td>{{.Название_жанра}}</td>
</li>
{{.end}}
</table>
</body>
</html>

Go HTML template

I have created a simple scraper that takes the top 10 news from a website and returns a JSON with the title and the score. I want to pass the title and the score as HTML template so I can generate a webpage. I'm not familiar with the templating Go language and I don't know how to pass the values for each of the links. Here is the HTML code that I should use and my implementation for now:
<!DOCTYPE html>
<html>
<head><linkrel="stylesheet" href="https://unpkg.com/mvp.css"
/>
</head>
<body>
<h1>{{.PageTitle}}</h1>
<ul>
{{range .Links}}
<li>{{.Title}}: {{.Score}}</li>
{{end}}
</ul>
</body>
</html>
My code:
package main
import (
"encoding/json"
"html/template"
"log"
"net/http"
"strconv"
)
type TopStories struct {
Title string `json:"title"`
Score int `json:"score"`
}
type TopStoriesPayload struct {
TopStories []TopStories
}
type NewsScraper struct {
url string
Data []TopStories
}
type templateData struct {
PageTitle string
Data []TopStories
}
func NewNewsScraper(url string) *NewsScraper {
return &NewsScraper{url: url}
}
func Top10Stories() []string {
req, err := http.NewRequest("GET", "https://hacker-news.firebaseio.com/v0/topstories.json", nil)
if err != nil {
log.Fatal(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
var IDs []int
json.NewDecoder(resp.Body).Decode(&IDs)
IDs = IDs[:10]
var IDsString []string
for _, id := range IDs {
IDsString = append(IDsString, strconv.Itoa(id))
}
return IDsString
}
func (n *NewsScraper) GetTopStories() {
req, err := http.NewRequest("GET", n.url, nil)
if err != nil {
log.Fatal(err)
}
for _, id := range Top10Stories() {
req.URL.Path = "/v0/item/" + id + ".json"
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
var topStory TopStories
json.NewDecoder(resp.Body).Decode(&topStory)
n.Data = append(n.Data, topStory)
}
}
//create html template handler for top stories
func HTMLHandler(w http.ResponseWriter, r *http.Request) {
scraper := NewNewsScraper("https://hacker-news.firebaseio.com")
scraper.GetTopStories()
tmpl:= template.Must(template.ParseFiles("template.html"))
data := templateData{
PageTitle: "Top Stories",
Data :[]TopStories{
//what should I put here?
},
}
tmpl.Execute(w, data)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/top", HTMLHandler)
http.ListenAndServe(":8080", mux)
}
I see three issues with your code:
a) The template.html file should have space between link & rel
<linkrel="stylesheet" href="https://unpkg.com/mvp.css"/>
to
<link rel="stylesheet" href="https://unpkg.com/mvp.css"/>
b) The template.html file should contain .Data instead of .Links.
c) The go code should be replaced from the below
Data :[]TopStories{
//what should I put here?
},
to
Data : scraper.Data,

Trying to render a template, getting an error html/template: "templates/index.html" is undefined

I have a simple main.go script that loads a template from a folder. The template looks like:
<html>
<head>
<title>T2 template</title>
</head>
<body>
hello
</body>
</html>
The main.go script looks is:
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"os"
"github.com/gorilla/mux"
)
var (
templates = template.Must(template.ParseFiles("templates/index.html"))
)
func main() {
port := os.Getenv("PORT")
fmt.Printf("port is: %v\n", port)
r := mux.NewRouter()
r.HandleFunc("/hello", HomeHandler)
log.Fatal(http.ListenAndServe(":"+port, r))
}
func HomeHandler(w http.ResponseWriter, r *http.Request) {
tmpl := "templates/index.html"
err := templates.ExecuteTemplate(w, tmpl, "")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
I'm not sure what is wrong here.
The error I see in the browser is:
"templates/index.html" is undefined
The ParseFiles doc says:
The returned template's name will have the (base) name and (parsed) contents of the first file.
To execute the template, use the base name of "templates/index.html":
tmpl := "index.html"
err := templates.ExecuteTemplate(w, tmpl, "")

How to open images in webserver

I have a simple webserver and I want to open imagesin browser. The problem is browser can't open an image I sent.
package main
import (
"io/ioutil"
"net/http"
"io"
"html/template"
"fmt"
)
func main() {
http.HandleFunc("/images", images)
http.ListenAndServe(":8080", nil)
}
func images(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("templates/link.html")
if err != nil {
fmt.Fprintf(w, err.Error())
return
}
t.ExecuteTemplate(w, "link", nil)
}
Also my html template package, where I create a link to file on my computer. Called link.html
{{ define "link" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p> apple</p>
<br>
</body>
</html>
{{ end }}
I do not understand why it doesn't work. Will be very glad for help. In addition all files I wanted to add to server are lying in this golang project
It's because you do not have any dedicated route that handles requests for any images.
My recommendation would be to initialize an HTTP handler that serves file based on the URI pathname. You can use that handler as a way to serve images.
fs := http.FileServer(http.Dir("images"))
And then to bind it:
http.Handle("/images/", http.StripPrefix("/images/", fs))
Here's your full code with my suggestions:
package main
import (
"fmt"
"html/template"
"net/http"
)
func main() {
// We're creating a file handler, here.
fs := http.FileServer(http.Dir("images"))
http.HandleFunc("/images", images)
// We're binding the handler to the `/images` route, here.
http.Handle("/images/", http.StripPrefix("/images/", fs))
http.ListenAndServe(":8080", nil)
}
func images(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("templates/link.html")
if err != nil {
fmt.Fprintf(w, err.Error())
return
}
t.ExecuteTemplate(w, "link", nil)
}

GO - get photos from flickr api

I'm new to Go. I'm trying to build a simple app that lets users get photos from flickr by keying in a tag in a form. I'm stuck at my current code (pasted below) as nothing appears on the page /showimage when I click on the submit button. What am I doing wrong in the code?
package main
import (
"encoding/json"
"fmt"
"html/template"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
)
func main() {
http.HandleFunc("/", handler)
http.HandleFunc("/showimage", showimage)
fmt.Println("listening...")
err := http.ListenAndServe(GetPort(), nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func GetPort() string {
var port = os.Getenv("PORT")
if port == "" {
port = "4747"
fmt.Println("INFO: No PORT environment variable detected, defaulting to " + port)
}
return ":" + port
}
func handler (w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, rootForm)
}
const rootForm =
`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Flickr photos</title>
</head>
<body>
<h1>Flickr photos</h1>
<p>Find photos by tags!</p>
<form action="/showimage" method="post" accept-charset="utf-8">
<input type="text" name="str" value="Type Tags..." id="str">
<input type="submit" value=".. and see the images!">
</form>
</body>
</html>`
var upperTemplate = template.Must(template.New("showimage").Parse(upperTemplateHTML))
func showimage(w http.ResponseWriter, r *http.Request) {
tag := r.FormValue("str")
safeTag := url.QueryEscape(tag)
apiKey := "MYAPIKEY"
fullUrl := fmt.Sprintf("https://api.flickr.com/services/rest/?method=flickr.people.getPhotos&api_key=%s&tags=%s", apiKey, safeTag)
client := &http.Client{}
req, err := http.NewRequest("GET", fullUrl, nil)
if err != nil {
log.Fatal("NewRequest: ", err)
return
}
resp, requestErr := client.Do(req)
if requestErr != nil {
log.Fatal("Do: ", requestErr)
return
}
defer resp.Body.Close()
body, dataReadErr := ioutil.ReadAll(resp.Body)
if dataReadErr != nil {
log.Fatal("ReadAll: ", dataReadErr)
return
}
res := make(map[string]map[string]map[string]interface{}, 0)
json.Unmarshal(body, &res)
owner, _ := res["photos"]["photo"]["owner"]
id, _ := res["photos"]["photo"]["id"]
queryUrl := fmt.Sprintf("http://flickr.com/photos/%s/%s", owner, id)
tempErr := upperTemplate.Execute(w, queryUrl)
if tempErr != nil {
http.Error(w, tempErr.Error(), http.StatusInternalServerError)
}
}
const upperTemplateHTML =
`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Display images</title>
</head>
<body>
<h3>Images</h3>
<img src="{{html .}}" alt="Image" />
</body>
</html>`
Two things:
1) http.HandleFunc("showimage", showimage) should be http.HandleFunc("/showimage", showimage)
2) MYAPIKEY is probably not a valid api key.

Resources