add debian building. add asset compile and embedding. other fixes.
This commit is contained in:
207
routes/paste.go
207
routes/paste.go
@@ -2,11 +2,8 @@ package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"sour.is/x/httpsrv"
|
||||
"sour.is/x/ident"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
@@ -15,29 +12,37 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"crypto/rand"
|
||||
"strconv"
|
||||
"sour.is/x/paste/model"
|
||||
"bufio"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var store string
|
||||
var randBytes int
|
||||
|
||||
func init() {
|
||||
httpsrv.HttpRegister("paste", httpsrv.HttpRoutes{
|
||||
{ "Paste", "GET", "/paste/rng", GetRandom, },
|
||||
{ "Paste", "GET", "/paste/{id}", GetPaste, },
|
||||
{ "Paste", "GET", "/paste/get/{id}", GetPaste, },
|
||||
{ "Paste", "POST", "/paste", PostPaste, },
|
||||
// { "Paste", "DELETE", "/paste/{id}", DeletePaste, },
|
||||
httpsrv.RegisterModule("paste", setConfig)
|
||||
|
||||
{ "Paste", "GET", "/api/rng", GetRandom, },
|
||||
{ "Paste", "GET", "/api/{id}", GetPaste, },
|
||||
{ "Paste", "GET", "/api/get/{id}", GetPaste, },
|
||||
{ "Paste", "POST", "/api", PostPaste, },
|
||||
// { "Paste", "DELETE", "/api/{id}", DeletePaste, },
|
||||
httpsrv.HttpRegister("paste", httpsrv.HttpRoutes{
|
||||
{ "getRandom", "GET", "/paste/rng", getRandom, },
|
||||
{ "getPaste", "GET", "/paste/{id}", getPaste, },
|
||||
{ "getPaste", "GET", "/paste/get/{id}", getPaste, },
|
||||
{ "postPaste", "POST", "/paste", postPaste, },
|
||||
|
||||
{ "getRandom", "GET", "/api/rng", getRandom, },
|
||||
{ "getPaste", "GET", "/api/{id}", getPaste, },
|
||||
{ "getPaste", "GET", "/api/get/{id}", getPaste, },
|
||||
{ "postPaste", "POST", "/api", postPaste, },
|
||||
})
|
||||
|
||||
httpsrv.AssetRegister("paste", httpsrv.AssetRoutes{
|
||||
{ "Assets", "/", httpsrv.FsHtml5( assetFS() ) },
|
||||
})
|
||||
}
|
||||
|
||||
func SetConfig (config map[string]string) {
|
||||
func setConfig (config map[string]string) {
|
||||
|
||||
store = "data/"
|
||||
if config["store"] != "" {
|
||||
@@ -45,16 +50,17 @@ func SetConfig (config map[string]string) {
|
||||
}
|
||||
|
||||
if !chkStore(store) {
|
||||
log.Fatalf("[routes::Paste] Store location [%s] does not exist or is not writable.", store)
|
||||
log.Criticalf("[routes::Paste] Store location [%s] does not exist or is not writable.", store)
|
||||
}
|
||||
log.Noticef("[paste::getPaste] Store location set to [%s]", store)
|
||||
|
||||
randBytes = 1024
|
||||
if config["random"] != "" {
|
||||
randBytes, _ = strconv.Atoi(config["random"])
|
||||
log.Noticef("[paste:getRandom] set random size to %d bytes", randBytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func chkStore(path string) bool {
|
||||
file, err := os.Stat(path)
|
||||
if err == nil { return true }
|
||||
@@ -82,120 +88,107 @@ func chkGone(path string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func GetRandom(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("content-type","application/octet-stream")
|
||||
func getRandom(w http.ResponseWriter, r *http.Request) {
|
||||
s := make([]byte, randBytes)
|
||||
rand.Read(s)
|
||||
|
||||
w.Header().Set("content-type","application/octet-stream")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(s)
|
||||
}
|
||||
// swagger:route GET /paste pasteIndex
|
||||
//
|
||||
// Welcomes user.
|
||||
//
|
||||
// This welcome user based on identity used.
|
||||
//
|
||||
// Consumes:
|
||||
// - application/json
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// Schemes: http
|
||||
//
|
||||
// Security:
|
||||
// user_token:
|
||||
//
|
||||
// Responses:
|
||||
// default: genericError
|
||||
// 200: someResponse
|
||||
// 422: validationError
|
||||
|
||||
func GetPaste(w http.ResponseWriter, r *http.Request, i ident.Ident) {
|
||||
func getPaste(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
p, err := model.GetPaste(id)
|
||||
log.Printf("%#v",p)
|
||||
|
||||
if !chkFile(store + id) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("ERR Not Found"))
|
||||
return
|
||||
}
|
||||
|
||||
if chkGone(store + id) {
|
||||
w.WriteHeader(http.StatusGone)
|
||||
w.Write([]byte("ERR Gone"))
|
||||
return
|
||||
}
|
||||
|
||||
head, err := os.Open(store + id)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte("Bad Request"))
|
||||
return
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer head.Close()
|
||||
|
||||
if p.Id == "" {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("Not Found"))
|
||||
return
|
||||
}
|
||||
keep := true
|
||||
scanner := bufio.NewScanner(head)
|
||||
for scanner.Scan() {
|
||||
txt := scanner.Text()
|
||||
log.Debug(txt)
|
||||
|
||||
//switch accept {
|
||||
//case "text/plain":
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if _, err := w.Write([]byte(p.String()));
|
||||
err != nil {
|
||||
panic(err)
|
||||
}
|
||||
/*
|
||||
case "application/json":
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if err := json.NewEncoder(w).Encode(p);
|
||||
err != nil {
|
||||
panic(err)
|
||||
if (txt == "") {
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotAcceptable)
|
||||
w.Write([]byte(""))
|
||||
if strings.HasPrefix(txt, "exp:") {
|
||||
now := time.Now().Unix()
|
||||
exp, err := strconv.ParseInt(strings.TrimSpace(strings.TrimPrefix(txt, "exp:")), 10, 64)
|
||||
if err != nil {
|
||||
log.Warning(err)
|
||||
}
|
||||
|
||||
log.Debugf("%d > %d", now, exp)
|
||||
if now > exp {
|
||||
w.WriteHeader(http.StatusGone)
|
||||
w.Write([]byte("ERR Gone"))
|
||||
|
||||
deleteFile(store + id)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(txt, "burn:") {
|
||||
burn := strings.TrimSpace(strings.TrimPrefix(txt, "burn:"))
|
||||
|
||||
if burn == "true" {
|
||||
keep = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file, _ := os.Open(store + id)
|
||||
defer file.Close()
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
scanner = bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
w.Write(scanner.Bytes())
|
||||
w.Write([]byte("\n"))
|
||||
}
|
||||
|
||||
if !keep {
|
||||
deleteFile(store + id)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
func PostPaste(w http.ResponseWriter, r *http.Request, i ident.Ident) {
|
||||
var p model.Paste
|
||||
func postPaste(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
|
||||
checkErr(err, w)
|
||||
|
||||
err = r.Body.Close()
|
||||
checkErr(err, w)
|
||||
s256 := sha256.Sum256(body)
|
||||
id := base64.RawURLEncoding.EncodeToString(s256[12:])
|
||||
|
||||
if err := json.Unmarshal(body, &p); err != nil {
|
||||
w.WriteHeader(422) // unprocessable entity
|
||||
err = json.NewEncoder(w).Encode(err)
|
||||
checkErr(err, w)
|
||||
}
|
||||
ioutil.WriteFile(store + id, body, 0644)
|
||||
|
||||
p.CreatedBy = i.Identity()
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte("OK " + id))
|
||||
|
||||
np, err := model.CreatePaste(p)
|
||||
checkErr(err, w)
|
||||
|
||||
// accept := negotiate.Negotiate("text/plain,application/json;q=0.7", r)
|
||||
|
||||
//switch accept {
|
||||
//case "text/plain":
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if _, err := w.Write([]byte(np.String()));
|
||||
err != nil {
|
||||
panic(err)
|
||||
}
|
||||
/*
|
||||
case "application/json":
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if err := json.NewEncoder(w).Encode(np);
|
||||
err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotAcceptable)
|
||||
w.Write([]byte(""))
|
||||
}
|
||||
*/
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
func checkErr(err error, w http.ResponseWriter) {
|
||||
@@ -204,4 +197,8 @@ func checkErr(err error, w http.ResponseWriter) {
|
||||
json.NewEncoder(w).Encode(err);
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func deleteFile(path string) {
|
||||
ioutil.WriteFile(path, []byte(""), 0644)
|
||||
}
|
||||
195
routes/paste.go.db
Normal file
195
routes/paste.go.db
Normal file
@@ -0,0 +1,195 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"sour.is/x/httpsrv"
|
||||
"os"
|
||||
"golang.org/x/sys/unix"
|
||||
"log"
|
||||
"net/http"
|
||||
"sour.is/x/ident"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"crypto/sha256"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"bufio"
|
||||
"github.com/gorilla/mux"
|
||||
"strings"
|
||||
"time"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var store string
|
||||
var randBytes int
|
||||
|
||||
func init() {
|
||||
httpsrv.RegisterModule("paste", SetConfig)
|
||||
|
||||
httpsrv.IdentRegister("paste", httpsrv.IdentRoutes{
|
||||
{ "Paste", "GET", "/paste/rng", GetRandom, },
|
||||
{ "Paste", "GET", "/paste/{id}", GetPaste, },
|
||||
{ "Paste", "GET", "/paste/get/{id}", GetPaste, },
|
||||
{ "Paste", "POST", "/paste", PostPaste, },
|
||||
{ "Paste", "DELETE", "/paste/{id}", DeletePaste, },
|
||||
|
||||
{ "Paste", "GET", "/api/rng", GetRandom, },
|
||||
{ "Paste", "GET", "/api/{id}", GetPaste, },
|
||||
{ "Paste", "GET", "/api/get/{id}", GetPaste, },
|
||||
{ "Paste", "POST", "/api", PostPaste, },
|
||||
{ "Paste", "DELETE", "/api/{id}", DeletePaste, },
|
||||
})
|
||||
}
|
||||
|
||||
func SetConfig (config map[string]string) {
|
||||
|
||||
store = "data/"
|
||||
if config["store"] != "" {
|
||||
store = config["store"]
|
||||
}
|
||||
|
||||
if !chkStore(store) {
|
||||
log.Fatalf("[routes::Paste] Store location [%s] does not exist or is not writable.", store)
|
||||
}
|
||||
|
||||
randBytes = 1024
|
||||
if config["random"] != "" {
|
||||
randBytes, _ = strconv.Atoi(config["random"])
|
||||
}
|
||||
}
|
||||
|
||||
func chkStore(path string) bool {
|
||||
file, err := os.Stat(path)
|
||||
if err == nil { return true }
|
||||
if os.IsNotExist(err) { return false }
|
||||
if !file.IsDir() { return false }
|
||||
if unix.Access(path, unix.W_OK & unix.R_OK) != nil { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func chkFile(path string) bool {
|
||||
file, err := os.Stat(path)
|
||||
if err == nil { return true }
|
||||
if os.IsNotExist(err) { return false }
|
||||
if file.IsDir() { return false }
|
||||
if unix.Access(path, unix.W_OK & unix.R_OK) != nil { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func chkGone(path string) bool {
|
||||
file, err := os.Stat(path)
|
||||
if err != nil { return true }
|
||||
if file.Size() == 0 { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
func GetRandom(w http.ResponseWriter, r *http.Request, i ident.Ident) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("content-type","application/octet-stream")
|
||||
s := make([]byte, randBytes)
|
||||
rand.Read(s)
|
||||
|
||||
w.Write(s)
|
||||
}
|
||||
|
||||
func GetPaste(w http.ResponseWriter, r *http.Request, i ident.Ident) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
if !chkFile(store + id) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("ERR Not Found"))
|
||||
return
|
||||
}
|
||||
|
||||
if chkGone(store + id) {
|
||||
w.WriteHeader(http.StatusGone)
|
||||
w.Write([]byte("ERR Gone"))
|
||||
return
|
||||
}
|
||||
|
||||
head, err := os.Open(store + id)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer head.Close()
|
||||
|
||||
keep := true
|
||||
|
||||
scanner := bufio.NewScanner(head)
|
||||
for scanner.Scan() {
|
||||
txt := scanner.Text()
|
||||
log.Println(txt)
|
||||
if (txt == "") {
|
||||
break
|
||||
}
|
||||
|
||||
if strings.HasPrefix(txt, "exp:") {
|
||||
now := time.Now().Unix()
|
||||
exp, err := strconv.ParseInt(strings.TrimSpace(strings.TrimPrefix(txt, "exp:")), 10, 64)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
if now > exp {
|
||||
log.Printf("%d > %d", now, exp)
|
||||
w.WriteHeader(http.StatusGone)
|
||||
w.Write([]byte("ERR Gone"))
|
||||
|
||||
Delete(store + id)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(txt, "burn:") {
|
||||
burn := strings.TrimSpace(strings.TrimPrefix(txt, "burn:"))
|
||||
|
||||
if burn == "true" {
|
||||
keep = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file, _ := os.Open(store + id)
|
||||
defer file.Close()
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
scanner = bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
w.Write(scanner.Bytes())
|
||||
w.Write([]byte("\n"))
|
||||
}
|
||||
|
||||
if !keep {
|
||||
Delete(store + id)
|
||||
}
|
||||
}
|
||||
|
||||
func PostPaste(w http.ResponseWriter, r *http.Request, i ident.Ident) {
|
||||
body, _ := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
|
||||
|
||||
s256 := sha256.Sum256(body)
|
||||
id := base64.RawURLEncoding.EncodeToString(s256[12:])
|
||||
|
||||
ioutil.WriteFile(store + id, body, 0644)
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte("OK " + id))
|
||||
}
|
||||
|
||||
func DeletePaste(w http.ResponseWriter, r *http.Request, i ident.Ident) {
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
Delete(store + id)
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
w.Write([]byte("OK"))
|
||||
}
|
||||
|
||||
func Delete(path string) {
|
||||
ioutil.WriteFile(path, []byte(""), 0644)
|
||||
}
|
||||
Reference in New Issue
Block a user