Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05978f7fc3 | ||
|
|
4c3a508b84 | ||
|
|
6733ccd4b8 | ||
|
|
2f0c09ff72 | ||
|
|
ff3ed3a57e | ||
|
|
39ca01c3e8 | ||
|
|
c457cb1daf | ||
|
|
73efeb0acf | ||
|
|
afcc33b76b | ||
|
|
6319c18ddd | ||
|
|
cb73169eeb | ||
|
|
b47327dfe6 | ||
|
|
097ca9b8c0 |
14
Dockerfile
14
Dockerfile
@@ -1,16 +1,16 @@
|
||||
FROM frolvlad/alpine-glibc:alpine-3.9_glibc-2.29
|
||||
RUN apk update \
|
||||
&& apk add --no-cache \
|
||||
ca-certificates \
|
||||
bash jq curl \
|
||||
php php-sqlite3 php-pdo php-pdo_mysql php-json php-pdo_sqlite
|
||||
|
||||
FROM golang:1.13-alpine as certs
|
||||
RUN apk update && apk add --no-cache ca-certificates
|
||||
|
||||
FROM busybox:glibc
|
||||
RUN mkdir -p /var/log
|
||||
WORKDIR /main
|
||||
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
|
||||
|
||||
COPY . .
|
||||
|
||||
ENV GOPATH=""
|
||||
ENV MNT="/mnt/"
|
||||
ENTRYPOINT ["/bin/bash", "/main/entrypoint.sh"]
|
||||
ENTRYPOINT ["/main/exec-todo-server"]
|
||||
CMD []
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ var (
|
||||
StoreAddr string
|
||||
StoreUser string
|
||||
StorePass string
|
||||
Root string
|
||||
MyTinyTodo string
|
||||
)
|
||||
|
||||
@@ -32,6 +33,7 @@ func Refresh() {
|
||||
as.Append(args.STRING, "storeuser", "user of store", "")
|
||||
as.Append(args.STRING, "storepass", "pass of store", "")
|
||||
as.Append(args.STRING, "mtt", "url of php server", "http://localhost:38808")
|
||||
as.Append(args.STRING, "root", "root of static files", "./public")
|
||||
if err := as.Parse(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -41,5 +43,6 @@ func Refresh() {
|
||||
StoreAddr = as.Get("storeaddr").GetString()
|
||||
StoreUser = as.Get("storeuser").GetString()
|
||||
StorePass = as.Get("storepass").GetString()
|
||||
Root = as.Get("root").GetString()
|
||||
MyTinyTodo = as.Get("mtt").GetString()
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
(
|
||||
pushd /main/testdata/mytinytodo*
|
||||
php -S 0.0.0.0:38808
|
||||
kill -9 1
|
||||
) &
|
||||
|
||||
(
|
||||
until curl localhost:39909; do
|
||||
sleep 1
|
||||
done
|
||||
pushd /main/testdata
|
||||
bash ./migrate.sh 192.168.0.86:44112 localhost:39909
|
||||
) &
|
||||
|
||||
exec /main/exec-todo-server "$@"
|
||||
@@ -61,6 +61,18 @@ func ToStrArr(k string) []string {
|
||||
}
|
||||
|
||||
func ToTime(s string) time.Time {
|
||||
v, _ := time.Parse("2006-01-02 15:04:05", s)
|
||||
v, err := time.Parse("2006-01-02 15:04:05", s)
|
||||
if err != nil || v.IsZero() {
|
||||
v, err = time.Parse("2006-01-02", s)
|
||||
}
|
||||
if err != nil || v.IsZero() {
|
||||
v, err = time.Parse("1/2/06", s)
|
||||
}
|
||||
if err != nil || v.IsZero() {
|
||||
v, err = time.Parse("02 Jan 2006 3:04 PM", s)
|
||||
}
|
||||
if err != nil || v.IsZero() {
|
||||
v, err = time.Parse("02 Jan 2006 3:04 PM", strings.ReplaceAll(s, "+", " "))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
@@ -79,6 +79,18 @@ func TestToTime(t *testing.T) {
|
||||
in: "5",
|
||||
out: "0001-01-01 00:00:00",
|
||||
},
|
||||
{
|
||||
in: "1/2/03",
|
||||
out: "2003-01-02 00:00:00",
|
||||
},
|
||||
{
|
||||
in: "11/12/03",
|
||||
out: "2003-11-12 00:00:00",
|
||||
},
|
||||
{
|
||||
in: "01+Jan+2020+12:00+PM",
|
||||
out: "2020-01-01 12:00:00",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
||||
@@ -94,6 +94,7 @@ func (a *Ajax) storageListTasks(listID string, filters ...func(t *task.Task) boo
|
||||
}
|
||||
}
|
||||
if filtered {
|
||||
//task.Title = fmt.Sprintf("[%d] %s", task.Index, task.Title)
|
||||
tasks = append(tasks, task)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,41 +7,21 @@ import (
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/task"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type taskWithDelta struct {
|
||||
task *task.Task
|
||||
delta int
|
||||
}
|
||||
|
||||
func (a *Ajax) loadTasks(w http.ResponseWriter, r *http.Request) error {
|
||||
listID, _, _ := a.Cur(r)
|
||||
filterComplete := func(t *task.Task) bool {
|
||||
if form.Get(r, "compl") == "" {
|
||||
return true
|
||||
}
|
||||
return form.Get(r, "compl") == "1" || !t.Complete
|
||||
}
|
||||
filterTags := func(t *task.Task) bool {
|
||||
if form.Get(r, "t") == "" {
|
||||
return true
|
||||
}
|
||||
whitelistTags := form.ToStrArr(form.Get(r, "t"))
|
||||
if len(whitelistTags) == 0 {
|
||||
return true
|
||||
}
|
||||
whitelistTagMap := make(map[string]struct{})
|
||||
for _, tag := range whitelistTags {
|
||||
whitelistTagMap[tag] = struct{}{}
|
||||
}
|
||||
for _, tag := range t.Tags {
|
||||
if _, ok := whitelistTagMap[tag]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
filterSubstr := func(t *task.Task) bool {
|
||||
substr := form.Get(r, "s")
|
||||
return substr == "" || strings.Contains(fmt.Sprintf("%+v", t), substr)
|
||||
}
|
||||
filterComplete := filterComplete(form.Get(r, "compl"))
|
||||
filterTags := filterTags(form.ToStrArr(form.Get(r, "t")))
|
||||
filterSubstr := filterSubstr(form.Get(r, "s"))
|
||||
tasks, err := a.storageListTasks(listID, filterComplete, filterTags, filterSubstr)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -49,6 +29,36 @@ func (a *Ajax) loadTasks(w http.ResponseWriter, r *http.Request) error {
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"list": tasks})
|
||||
}
|
||||
|
||||
func filterComplete(compl string) func(t *task.Task) bool {
|
||||
return func(t *task.Task) bool {
|
||||
return compl == "" || !t.Complete || (compl == "1" && t.Complete)
|
||||
}
|
||||
}
|
||||
|
||||
func filterTags(tags []string) func(t *task.Task) bool {
|
||||
return func(t *task.Task) bool {
|
||||
for _, whitelisted := range tags {
|
||||
found := false
|
||||
for _, tag := range t.Tags {
|
||||
if whitelisted == tag {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func filterSubstr(substr string) func(t *task.Task) bool {
|
||||
return func(t *task.Task) bool {
|
||||
found := substr == "" || strings.Contains(strings.ToLower(fmt.Sprintf("%+v %+v", t.Title, t.Tags)), strings.ToLower(substr))
|
||||
return found
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Ajax) newTask(w http.ResponseWriter, r *http.Request) error {
|
||||
listID, newTask, err := a.makeTask(r)
|
||||
if err != nil {
|
||||
@@ -83,7 +93,10 @@ func (a *Ajax) makeTask(r *http.Request) (string, *task.Task, error) {
|
||||
|
||||
func (a *Ajax) deleteTask(w http.ResponseWriter, r *http.Request) error {
|
||||
_, taskID, _ := a.Cur(r)
|
||||
return a.storageDelTask(taskID)
|
||||
if err := a.storageDelTask(taskID); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"total": 0})
|
||||
}
|
||||
|
||||
func (a *Ajax) completeTask(w http.ResponseWriter, r *http.Request) error {
|
||||
@@ -107,45 +120,57 @@ func (a *Ajax) completeTask(w http.ResponseWriter, r *http.Request) error {
|
||||
|
||||
func (a *Ajax) editNote(w http.ResponseWriter, r *http.Request) error {
|
||||
listID, taskID, _ := a.Cur(r)
|
||||
task, err := a.storageGetTask(taskID)
|
||||
editedTask, err := a.storageGetTask(taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.SetNote(form.Get(r, "note"))
|
||||
return a.storageSetTask(listID, task)
|
||||
editedTask.SetNote(form.Get(r, "note"))
|
||||
if err := a.storageSetTask(listID, editedTask); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{editedTask}})
|
||||
}
|
||||
|
||||
func (a *Ajax) editTask(w http.ResponseWriter, r *http.Request) error {
|
||||
listID, task, err := a.makeTask(r)
|
||||
listID, editedTask, err := a.makeTask(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, taskID, _ := a.Cur(r)
|
||||
task.UUID = taskID
|
||||
return a.storageSetTask(listID, task)
|
||||
editedTask.UUID = taskID
|
||||
if err := a.storageSetTask(listID, editedTask); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{editedTask}})
|
||||
}
|
||||
|
||||
func (a *Ajax) setPrio(w http.ResponseWriter, r *http.Request) error {
|
||||
listID, taskID, _ := a.Cur(r)
|
||||
task, err := a.storageGetTask(taskID)
|
||||
editedTask, err := a.storageGetTask(taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.SetPrio(form.ToInt(form.Get(r, "prio")))
|
||||
return a.storageSetTask(listID, task)
|
||||
editedTask.SetPrio(form.ToInt(form.Get(r, "prio")))
|
||||
if err := a.storageSetTask(listID, editedTask); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{editedTask}})
|
||||
}
|
||||
|
||||
func (a *Ajax) moveTask(w http.ResponseWriter, r *http.Request) error {
|
||||
_, taskID, _ := a.Cur(r)
|
||||
toList := form.Get(r, "to")
|
||||
task, err := a.storageGetTask(taskID)
|
||||
movedTask, err := a.storageGetTask(taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := a.storageDelTask(taskID); err != nil {
|
||||
return err
|
||||
}
|
||||
return a.storageSetTask(toList, task)
|
||||
if err := a.storageSetTask(toList, movedTask); err != nil {
|
||||
return err
|
||||
}
|
||||
return json.NewEncoder(w).Encode(map[string]interface{}{"total": 1, "list": []*task.Task{movedTask}})
|
||||
}
|
||||
|
||||
func (a *Ajax) parseTaskStr(w http.ResponseWriter, r *http.Request) error {
|
||||
@@ -155,8 +180,8 @@ func (a *Ajax) parseTaskStr(w http.ResponseWriter, r *http.Request) error {
|
||||
func (a *Ajax) changeOrder(w http.ResponseWriter, r *http.Request) error {
|
||||
order := form.Get(r, "order")
|
||||
orders := strings.Split(order, "&")
|
||||
sum := 0
|
||||
zero := ""
|
||||
modified := make([]taskWithDelta, 0)
|
||||
indices := make([]int, 0)
|
||||
for _, order := range orders {
|
||||
taskIDDelta := strings.Split(order, "=")
|
||||
if len(taskIDDelta) < 2 {
|
||||
@@ -164,43 +189,34 @@ func (a *Ajax) changeOrder(w http.ResponseWriter, r *http.Request) error {
|
||||
}
|
||||
taskID := taskIDDelta[0]
|
||||
delta, _ := strconv.Atoi(taskIDDelta[1])
|
||||
if delta < 0 {
|
||||
delta = -1
|
||||
} else {
|
||||
delta = 0
|
||||
}
|
||||
task, err := a.storageGetTask(taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listID, err := a.taskIDToListID(taskID)
|
||||
modified = append(modified, taskWithDelta{task: task, delta: delta})
|
||||
indices = append(indices, task.Index)
|
||||
}
|
||||
sort.Slice(modified, func(i, j int) bool {
|
||||
if modified[i].delta < modified[j].delta {
|
||||
return true
|
||||
} else if modified[i].delta > modified[j].delta {
|
||||
return false
|
||||
}
|
||||
return modified[i].task.Index < modified[j].task.Index
|
||||
})
|
||||
sort.Ints(indices)
|
||||
for i := 0; i < len(modified); i++ {
|
||||
task := *modified[i].task
|
||||
task.Index = indices[i]
|
||||
listID, err := a.taskIDToListID(task.UUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.Index += delta
|
||||
if err := a.storageSetTask(listID, task); err != nil {
|
||||
if err := a.storageSetTask(listID, &task); err != nil {
|
||||
return err
|
||||
}
|
||||
if delta == 0 {
|
||||
zero = taskID
|
||||
}
|
||||
sum += delta
|
||||
}
|
||||
if zero == "" || sum == 0 {
|
||||
return nil
|
||||
}
|
||||
task, err := a.storageGetTask(zero)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listID, err := a.taskIDToListID(zero)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.Index -= sum
|
||||
if err := a.storageSetTask(listID, task); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprint(w, `{"total":1}`)
|
||||
|
||||
fmt.Fprintf(w, `{"total":1}`)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func New(r *http.Request) (*Task, error) {
|
||||
UUID: form.NewUUID(),
|
||||
Title: form.Get(r, "title"),
|
||||
Priority: form.ToInt(form.Get(r, "prio")),
|
||||
Tags: StrList(form.ToStrArr(form.Get(r, "tags"))),
|
||||
Tags: append(StrList(form.ToStrArr(form.Get(r, "tag"))), StrList(form.ToStrArr(form.Get(r, "tags")))...),
|
||||
Created: time.Now(),
|
||||
Edited: time.Now(),
|
||||
|
||||
@@ -110,6 +110,13 @@ func (t *Task) MarshalJSON() ([]byte, error) {
|
||||
"dueInt": t.Due.Unix(),
|
||||
"dueTitle": "Due ",
|
||||
}
|
||||
if t.Due.IsZero() {
|
||||
for k := range m {
|
||||
if strings.HasPrefix(k, "due") {
|
||||
delete(m, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
if t.Complete {
|
||||
m["dateCompleted"] = t.Completed.Format(fullFormat)
|
||||
m["dateCompletedInline"] = t.Completed.Format(shortFormat)
|
||||
|
||||
@@ -2,6 +2,7 @@ package ajax
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"local/todo-server/server/ajax/form"
|
||||
"local/todo-server/server/ajax/task"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -207,3 +208,49 @@ func TestAjaxChangeOrder(t *testing.T) {
|
||||
t.Error(tasks[2])
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterComplete(t *testing.T) {
|
||||
cases := []struct {
|
||||
query string
|
||||
task bool
|
||||
out bool
|
||||
}{
|
||||
{query: "", out: true, task: false},
|
||||
{query: "0", out: true, task: false},
|
||||
{query: "1", out: true, task: false},
|
||||
}
|
||||
|
||||
for name, c := range cases {
|
||||
task := &task.Task{Complete: c.task}
|
||||
out := filterComplete(c.query)
|
||||
if out(task) != c.out {
|
||||
t.Errorf("[%d] want %v, got %v", name, c.out, out(task))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterTags(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
query string
|
||||
tags []string
|
||||
out bool
|
||||
}{
|
||||
"no filter": {query: "", out: true},
|
||||
"single matching filter": {query: "a", out: true, tags: []string{"a"}},
|
||||
"single non-matching filter": {query: "a", out: false, tags: []string{"b"}},
|
||||
"duo matching filter": {query: "a, b", out: true, tags: []string{"b", "a"}},
|
||||
"duo partial-matching filter": {query: "a, c", out: false, tags: []string{"b", "a"}},
|
||||
"duo non-matching filter": {query: "a, c", out: false, tags: []string{"d", "e"}},
|
||||
"trio matching filter": {query: "a, b, c", out: true, tags: []string{"b", "a", "c", "d", "e"}},
|
||||
"trio partial-matching filter": {query: "a, c, d", out: false, tags: []string{"b", "a", "d"}},
|
||||
"trio non-matching filter": {query: "a, b, c", out: false, tags: []string{"x", "y", "z"}},
|
||||
}
|
||||
|
||||
for name, c := range cases {
|
||||
task := &task.Task{Tags: c.tags}
|
||||
out := filterTags(form.ToStrArr(c.query))
|
||||
if v := out(task); v != c.out {
|
||||
t.Errorf("[%s] want %v, got %v", name, c.out, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@ package server
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"local/gziphttp"
|
||||
"local/router"
|
||||
"local/todo-server/config"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func (s *Server) Routes() error {
|
||||
@@ -19,12 +20,20 @@ func (s *Server) Routes() error {
|
||||
handler http.HandlerFunc
|
||||
}{
|
||||
{
|
||||
path: fmt.Sprintf("%s%s", router.Wildcard, router.Wildcard),
|
||||
handler: s.phpProxy,
|
||||
path: "/",
|
||||
handler: s.gzip(s.index),
|
||||
},
|
||||
{
|
||||
path: fmt.Sprintf("ajax.php"),
|
||||
handler: s.HandleAjax,
|
||||
path: "/mytinytodo_lang.php",
|
||||
handler: s.gzip(s.lang),
|
||||
},
|
||||
{
|
||||
path: fmt.Sprintf("%s%s", router.Wildcard, router.Wildcard),
|
||||
handler: s.gzip(s.phpProxy),
|
||||
},
|
||||
{
|
||||
path: "/ajax.php",
|
||||
handler: s.gzip(s.HandleAjax),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -36,10 +45,39 @@ func (s *Server) Routes() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) lang(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, `
|
||||
mytinytodo.lang.init({
|
||||
confirmDelete: "Are you sure you want to delete the task?",
|
||||
confirmLeave: "There can be unsaved data. Do you really want to leave?",
|
||||
actionNoteSave: "save",
|
||||
actionNoteCancel: "cancel",
|
||||
error: "Some error occurred (click for details)",
|
||||
denied: "Access denied",
|
||||
invalidpass: "Wrong password",
|
||||
tagfilter: "Tag:",
|
||||
addList: "Create new list",
|
||||
addListDefault: "Todo",
|
||||
renameList: "Rename list",
|
||||
deleteList: "This will delete current list with all tasks in it.\nAre you sure?",
|
||||
clearCompleted: "This will delete all completed tasks in the list.\nAre you sure?",
|
||||
settingsSaved: "Settings saved. Reloading...",
|
||||
daysMin: ["Su","Mo","Tu","We","Th","Fr","Sa"],
|
||||
daysLong: ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
|
||||
monthsLong: ["January","February","March","April","May","June","July","August","September","October","November","December"],
|
||||
tags: "Tags",
|
||||
tasks: "Tasks",
|
||||
f_past: "Overdue",
|
||||
f_today: "Today and tomorrow",
|
||||
f_soon: "Soon"
|
||||
});
|
||||
`)
|
||||
}
|
||||
|
||||
func (s *Server) index(w http.ResponseWriter, r *http.Request) {
|
||||
f, err := os.Open(path.Join(config.MyTinyTodo, "index.php"))
|
||||
f, err := os.Open(path.Join(config.Root, "index.html"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
@@ -47,11 +85,37 @@ func (s *Server) index(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (s *Server) phpProxy(w http.ResponseWriter, r *http.Request) {
|
||||
switch filepath.Ext(r.URL.Path) {
|
||||
case ".php":
|
||||
default:
|
||||
s.static(w, r)
|
||||
return
|
||||
}
|
||||
url, err := url.Parse(config.MyTinyTodo)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
} else {
|
||||
proxy := httputil.NewSingleHostReverseProxy(url)
|
||||
proxy.ServeHTTP(w, r)
|
||||
log.Println("WOULD proxy", url.String(), r.URL.Path)
|
||||
s.index(w, r)
|
||||
//proxy := httputil.NewSingleHostReverseProxy(url)
|
||||
//proxy.ServeHTTP(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) static(w http.ResponseWriter, r *http.Request) {
|
||||
s.fileServer.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (s *Server) gzip(h http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if gziphttp.Can(r) {
|
||||
gz := gziphttp.New(w)
|
||||
defer gz.Close()
|
||||
w = gz
|
||||
}
|
||||
if filepath.Ext(r.URL.Path) == ".css" {
|
||||
w.Header().Set("Content-Type", "text/css; charset=utf-8")
|
||||
}
|
||||
h(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@ package server
|
||||
|
||||
import (
|
||||
"local/router"
|
||||
"local/todo-server/config"
|
||||
"local/todo-server/server/ajax"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
*ajax.Ajax
|
||||
*router.Router
|
||||
fileServer http.Handler
|
||||
}
|
||||
|
||||
func New() *Server {
|
||||
@@ -15,8 +18,10 @@ func New() *Server {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fileServer := http.FileServer(http.Dir(config.Root))
|
||||
return &Server{
|
||||
Ajax: ajax,
|
||||
Router: router.New(),
|
||||
Ajax: ajax,
|
||||
Router: router.New(),
|
||||
fileServer: fileServer,
|
||||
}
|
||||
}
|
||||
|
||||
0
source_to_run_loaded.sh
Normal file → Executable file
0
source_to_run_loaded.sh
Normal file → Executable file
2
testdata/migrate.sh
vendored
Normal file → Executable file
2
testdata/migrate.sh
vendored
Normal file → Executable file
@@ -114,6 +114,6 @@ function b64decode() {
|
||||
}
|
||||
|
||||
if [ "$0" == "$BASH_SOURCE" ]; then
|
||||
echo bash migrate.sh 192.168.0.86:44112 localhost:39909
|
||||
echo bash migrate.sh 192.168.0.86:44112 localhost:38809
|
||||
time main "$@"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user