-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathgo-http.go
169 lines (134 loc) · 3.67 KB
/
go-http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"strconv"
"strings"
"time"
)
var defaultPath string
var baseURL string
func Logger(req *http.Request, statusCode int) {
const layout = "[ 2/Jan/2006 15:04:05 ]"
fmt.Println(baseURL + " --- " + time.Now().Format(layout) + " " + req.Method + " " + strconv.Itoa(statusCode) + " " + req.URL.Path)
}
func Handler(w http.ResponseWriter, req *http.Request) {
filename := defaultPath + req.URL.Path[1:]
if last := len(filename) - 1; last >= 0 && filename[last] == '/' && len(filename) != 1 {
filename = filename[:last]
}
// Empty request (Root)
if filename == "" {
filename = "./"
}
file, err := os.Stat(filename)
// 404 if file doesn't exist
if os.IsNotExist(err) {
_, err = io.WriteString(w, "404 Not Found")
Logger(req, http.StatusNotFound)
return
}
// Serve directory
if file.IsDir() {
slashCheck := ""
files, err := ioutil.ReadDir(filename)
// Catch the Error in reading from directory
if err != nil {
http.Redirect(w, req, "", http.StatusInternalServerError)
Logger(req, http.StatusInternalServerError)
}
// Checking for Root Directory
if filename != "./" {
if filename[len(filename)-1] != '/' {
slashCheck = "/"
}
}
responseString := "<html><body> <h3> Directory Listing for " + req.URL.Path[1:] + "/ </h3> <br/> <hr> <ul>"
for _, f := range files {
if f.Name()[0] != '.' {
if f.IsDir() {
responseString += "<li><a href=\"" + req.URL.Path[0:] + slashCheck + f.Name() + "\">" + f.Name() + "/" + "</a></li>"
} else {
responseString += "<li><a href=\"" + req.URL.Path[0:] + slashCheck + f.Name() + "\">" + f.Name() + "</a></li>"
}
}
}
//Ending the list
responseString += "</ul><br/><hr/>"
p := req.URL.Path
// Display link to parent directory
if len(p) > 1 {
base := path.Base(p)
slice := len(p) - len(base) - 1
url := "/"
if slice > 1 {
url = req.URL.Path[:slice]
url = strings.TrimRight(url, "/") // Remove extra / at the end
}
responseString += "<br/><a href=\"" + url + "\">Parent directory</a>"
}
responseString = responseString + "</body></html>"
_, err = io.WriteString(w, responseString)
if err != nil {
// panic(err)
http.Redirect(w, req, "", http.StatusInternalServerError)
Logger(req, http.StatusInternalServerError)
} else {
Logger(req, http.StatusOK)
}
return
}
// File exists and is no directory; Serve the file
b, err := ioutil.ReadFile(filename)
if err != nil {
http.Redirect(w, req, "", http.StatusInternalServerError)
Logger(req, http.StatusInternalServerError)
return
}
str := string(b)
extension := path.Ext(filename)
if extension == ".css" {
w.Header().Set("Content-Type", "text/css; charset=utf-8")
} else if extension == ".js" {
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
}
_, err = io.WriteString(w, str)
if err != nil {
// panic(err)
http.Redirect(w, req, "", http.StatusInternalServerError)
} else {
Logger(req, http.StatusOK)
}
}
func main() {
defaultPortPtr := flag.String("p", "", "Port Number")
defaultPathPtr := flag.String("d", "", "Root Directory")
flag.Parse()
portNum := "8080"
// Handling the command line flags
// Directory
if *defaultPathPtr != "" {
defaultPath = "./" + *defaultPathPtr + "/"
} else {
defaultPath = ""
}
// Port Number
if *defaultPortPtr != "" {
portNum = *defaultPortPtr
} else {
portNum = "8080"
}
baseURL = "http://localhost:" + portNum
fmt.Println("Serving on ", baseURL, " subdirectory ", defaultPath)
http.HandleFunc("/", Handler)
err := http.ListenAndServe(":"+portNum, nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}