do virtual URLs have a working directory?

219 views
Skip to first unread message

Hotei

unread,
Mar 1, 2012, 12:54:31 AM3/1/12
to golang-nuts
I'm trying to adapt the go HelloServer example to serve up some images
constructed by a go program writing svg in the local directory. When I
point a browser to it I get the 'broken-image' icon for the "local"
image but I can pull the same image from apache running on another
host. At this point I'm not sure that what I want to do can be done
since the "URL" 127.0.0.1/hello doesn't refer to anything in the
localhost directory tree. I know I can solve this by running
another go server instance to serve just the image directory at a
different port but that seems more cumbersome than necessary. And it
didn't work when given the full path (with search/read perms for all)
as opposed to the relative path in the code below. Any hints on better
ways would be most welcome. Thanks in advance.

Minimal code to reproduce problem (with weekly 2-22) follows:
// ====================
// zero.svg is in same directory as executable
// browse to 127.0.0.1/hello shows page text, but not image

package main

import (
"fmt"
"log"
"net/http"
)

const portNum = 12349
var portNumString = fmt.Sprintf(":%d",portNum)

func createSvg(name string) {
//..... svg writing code deleted for brevity .....
}

func HelloServer(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "<html>")
fmt.Fprintf(w, "<head>")
fmt.Fprintf(w, "<title>Test Title</title>")
fmt.Fprintf(w, "</head>")
fmt.Fprintf(w, "<body>")
fmt.Fprintf(w, "IMAGE --> <img src =\"zero.svg\">") // <-- gives
'broken-image' icon in Chrome
fmt.Fprintf(w, "IMAGE --> <img src =\"http://10.1.2.106/gallery/
zero.svg\">") // <-- works fine
fmt.Fprintf(w, "</body>")
fmt.Fprintf(w, "</html>")
}

func main(){
createSvg("zero.svg")
fmt.Printf("Starting server at %s\n",portNumString)
http.HandleFunc("/hello", HelloServer)
err := http.ListenAndServe(portNumString, nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}

Kyle Lemons

unread,
Mar 1, 2012, 1:03:09 AM3/1/12
to Hotei, golang-nuts
static/zero.svg
 
       fmt.Fprintf(w, "IMAGE --> <img src =\"http://10.1.2.106/gallery/
zero.svg\">")  // <-- works fine
       fmt.Fprintf(w, "</body>")
       fmt.Fprintf(w, "</html>")
}

func main(){
       createSvg("zero.svg")
 
       fmt.Printf("Starting server at %s\n",portNumString)
       http.HandleFunc("/hello", HelloServer)

http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))

and put the svg inside a "static" subdirectory.

       err := http.ListenAndServe(portNumString, nil)
       if err != nil {
               log.Fatal("ListenAndServe: ", err)
       }
}

You could use "." in the FileServer and avoid the StripPrefix, but in general you don't want to be serving source files blindly :)

Sanjay Menakuru

unread,
Mar 1, 2012, 3:10:18 AM3/1/12
to golan...@googlegroups.com, Hotei
Also, multiline strings are your friend when writing inline html. As is package text/template.

Here's an example of what I mean: http://play.golang.org/p/1GUHo1Ace6

If you do it that way, when your html becomes big enough to warrant its own file, its as simple as changing it from .Parse to .ParseFiles.

Cheers,
Sanjay

PS - If you're wondering why I write to a buffer, then to the ResponseWriter, it's so I can return an appropriate HTTP response code.

Sanjay Menakuru

unread,
Mar 1, 2012, 3:16:26 AM3/1/12
to golan...@googlegroups.com, Hotei
That is to say, return an appropriate response code in case of an error

Sanjay Menakuru

unread,
Mar 1, 2012, 3:18:33 AM3/1/12
to golan...@googlegroups.com, Hotei
Also, my example used text/template, you should almost certainly use html/template to be safe.

Hotei

unread,
Mar 1, 2012, 2:25:43 PM3/1/12
to golang-nuts
Thanks to the suggestions by Kyle and Sanjay it works exactly the way
I wanted it.  I incorporated both their suggestions and we're off and
running!!!  Thanks again for the insanely fast responses from both.

If anyone's interested I can post the example code on github.

Postscript:
The final answer to my original question seems to be that virtual URLs
(like /hello) can have the equivalent of a working directory anywhere
in your filesystem.  Kyle's suggestion let me set it to the user's
local directory where hello_server was executed or optionally to move
the working directory to a safe public tree like /www .  Sanjay's
contribution provides an extra level of error checking and allows the
code to safely execute in a concurrent environment.  Combining the
generation of graphic output with a web-server to browse it will allow
me to "package" the final application as a single executable. Three
years ago I would never have imagined doing that with a couple of
dozen extra lines of code.  Go is amazing.

Reply all
Reply to author
Forward
0 new messages