使用golang的标准库搭建网站--4.关于静态资源处理的问题

这里好像没有人 · · 947 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

建网站不可避免的要使用各种各样的静态资源,这一节,就来看看,如何加载css,js图片等等这些资源。

在之前的基础上构造一简单的个HTML的测试文件

<HTML> <head> <title>Hello World</title> <link href="static/core.css" type="text/css" rel="stylesheet" /> </head> <body> <div id="header"> <p>this is header</p> </div> <div id="main"> <p> this is main<br /> {{.Name | showname}} </p> </div> <div id="footer"> <p>this is footer</p> </div> </body> </HTML>

再创建一个css文件:

* { font-size: 30px; font-weight: bold; }
#header { background-color: red }
#main { background-color: yellow; }
#footer { background-color: blue; }

然后运行之前的go文件,结果如下:

这里写图片描述

从运行结果来看,会发现css并没有起作用,我们来看一看为什么会这样:
先做一个简单的测试:
我们之前在main方法中注册了一个路由:

http.HandleFunc("/", Index)

我们期望的是当直接访问 http://localhost:8080 时就能转到index.html
页面。
但事实上呢?
我们来试一试这个地址:
http://localhost:8080/core.css
同样的得到的是index.html这个页面的内容,
也就是说我们注册的路由也匹配到了/core.css这个请求

问题出在哪里呢?
我们得自己写一个路由函数,来看看是如何匹配路由的:
先看一下go的文档:看看ListenAndServe函数的声明:

func ListenAndServe(addr string, handler Handler) error

如果要自己写路由函数的话,就得先实现Handler这个接口,声明如下:

type Handler interface { ServeHTTP(ResponseWriter, *Request) }

先声明一个结构体:

type MyMux struct { routers map[string]func(http.ResponseWriter,*http.Request) }

实现ServeHTTP方法:

func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    //遍历routers,寻找匹配的path
    for path, f := range p.routers {
        if r.URL.Path == path {
            f(w, r)
            return
        }
    }
    fmt.Fprintf(w, "Error: Don't match URL '%s'", r.URL.Path)
}

重写main函数:

func main() {
    mux := &MyMux{}
    mux.routers = make(map[string]func(http.ResponseWriter, *http.Request))
    mux.routers["/"] = Index
    err := http.ListenAndServe(":8080", mux)
    if err != nil {
        fmt.Println("Error: ", err)
    }
}

这样的话对于每一次的请求,都遍历一次mux.routers,来查找是否有匹配到的路由,
但很显然,如果使用 “r.URL.Path == path” 这样的方式,是没法满足要求的,
因为你得列出每一种可能出现的path,这明显是不现实的,我们接下来考虑使用正则表达式来匹配路由规则。

我们需要重新实现ServeHTTP方法,但也只需要修改if的判断条件即可:
但不要忘了导入regexp正则表达式包

if ok, _ :=regexp.MatchString("^" + path + "$", r.URL.Path); ok { f(w, r) return }

并且新增一条是用正则表达式的路由:

mux.routers["/static/.+"] = Static

接下来,我们就要针对匹配到的static文件中的文件做单独的处理

func Static(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Deal Static: ", r.URL.Path)
    w.Header().Set("Content-Type", "text/css")
    http.ServeFile(w, r, "." + r.URL.Path)
}

现在再通过浏览器分别访问一下URL:
http://localhost:8080/
http://localhost:8080/static/core.css
发现已经匹配正常了。
虽然丑了点,但不要在意那么多细节啦,只是用来演示一下。

当我们访问 http://localhost:8080/ 的时候,浏览器会向服务器发送一个GET /static/core.css
的请求,服务器会匹配到 /static/.+ 这条规则,然后调用func Static()函数,那么在该函数中的
r.URL.Path则是/static/core.css,如果/static目录下还有多个文件夹的话,还要对r.URL.Path的值
另作处理,这里就不在展开说明了。

此时,当我们访问 http://localhost:8080/ 的时候,就会发现页面解析正常了,效果如下:
这里写图片描述
同理,js和图片以及其他静态资源都可以按照上面的方法处理。


有疑问加站长微信联系(非本文作者)

本文来自:开源中国博客

感谢作者:这里好像没有人

查看原文:使用golang的标准库搭建网站--4.关于静态资源处理的问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

947 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传