summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2016-07-23 16:34:39 (GMT)
committerChristian Pointner <equinox@helsinki.at>2016-07-23 16:34:39 (GMT)
commitbb9497361b566884a1e4cb6d76a6f539383bd32c (patch)
treed8dbf2a8fa4e98258ebe5aa6fb36f8e72e018d66 /src
parent2f2d09ea5aa99f1c80b12fc4e088ffc2248d690b (diff)
greatly simplified web uploads
Diffstat (limited to 'src')
-rw-r--r--src/rhimportd/routeWeb.go2
-rw-r--r--src/rhimportd/uploadWeb.go93
2 files changed, 16 insertions, 79 deletions
diff --git a/src/rhimportd/routeWeb.go b/src/rhimportd/routeWeb.go
index 22db1d7..d0582a2 100644
--- a/src/rhimportd/routeWeb.go
+++ b/src/rhimportd/routeWeb.go
@@ -50,7 +50,7 @@ func StartWebRouter(addr, staticDir string, conf *rhimport.Config, db *rddb.DBCh
// http.Handle("/trusted/simple", webHandler{conf, db, sessions, true, webSimpleHandler})
http.Handle("/public/simple", webHandler{conf, db, sessions, false, webSimpleHandler})
http.Handle("/public/socket", webHandler{conf, db, sessions, false, webSocketHandler})
- http.Handle("/public/upload", webHandler{conf, db, sessions, false, webUploadHandler})
+ http.Handle("/public/upload/", http.StripPrefix("/public/upload/", webHandler{conf, db, sessions, false, webUploadHandler}))
rhl.Println("web-router: listening on", addr)
server := &http.Server{Addr: addr, ReadTimeout: 2 * time.Hour, WriteTimeout: 2 * time.Hour}
diff --git a/src/rhimportd/uploadWeb.go b/src/rhimportd/uploadWeb.go
index 84605e6..9d16e92 100644
--- a/src/rhimportd/uploadWeb.go
+++ b/src/rhimportd/uploadWeb.go
@@ -25,11 +25,10 @@
package main
import (
- "bytes"
"encoding/json"
"io"
- "mime/multipart"
"net/http"
+ "strings"
"code.helsinki.at/rhrd-go/rddb"
"code.helsinki.at/rhrd-go/rhimport"
@@ -56,107 +55,45 @@ func webUploadSuccessResponse(w http.ResponseWriter) {
encoder.Encode(respdata)
}
-const (
- webUploadMaxRequestSize = (2 << 30) - 1 // 2GB, (2 << 30) overflows int on 32-bit systems therefore we use 2GB - 1 Byte
-)
-
-func webUploadParseForm(r *http.Request) (username, sessionid, srcfile string, src *multipart.Part, err error) {
- var mpr *multipart.Reader
- if mpr, err = r.MultipartReader(); err != nil {
- return
- }
-
- for {
- var p *multipart.Part
- if p, err = mpr.NextPart(); err != nil {
- if err == io.EOF {
- err = nil
- }
- return
- }
- var dstfield *string
- switch p.FormName() {
- case "LOGIN_NAME":
- dstfield = &username
- case "SESSION_ID":
- dstfield = &sessionid
- case "FILENAME":
- srcfile = p.FileName()
- src = p
- return // don't read any fields beyond this point because we would need to load the whole file in order to continue parsing
- default:
- rhdl.Printf("WebUploadHandler: ingoring unknown form field: '%s'", p.FormName())
- continue
- }
-
- var buf bytes.Buffer
- if _, err = io.CopyN(&buf, p, 1<<10); err != nil && err != io.EOF { // 1kB should be enough
- return
- }
- *dstfield = buf.String()
- p.Close()
- }
-}
-
func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport.SessionStoreChan, trusted bool, w http.ResponseWriter, r *http.Request) {
- if r.Method == "GET" {
- http.Redirect(w, r, "/static/upload.html", http.StatusTemporaryRedirect)
- return
- }
+ rhdl.Printf("WebUploadHandler: got request for %s", r.URL.String())
if r.Method != "POST" {
rhl.Printf("WebUploadHandler: got invalid request method")
- webUploadErrorResponse(w, http.StatusMethodNotAllowed, "only POST and GET method are allowed")
- return
- }
-
- // This is from: stackoverflow.com/questions/26392196
- if r.ContentLength > webUploadMaxRequestSize {
- rhl.Printf("WebUploadHandler: request is too large: %d > %d", r.ContentLength, webUploadMaxRequestSize)
- webUploadErrorResponse(w, http.StatusExpectationFailed, "request too large")
+ webUploadErrorResponse(w, http.StatusMethodNotAllowed, "only POST method is allowed")
return
}
- r.Body = http.MaxBytesReader(w, r.Body, webUploadMaxRequestSize)
- username, sessionid, srcfile, src, err := webUploadParseForm(r)
- if err != nil {
- rhl.Printf("WebUploadHandler: error while parsing multipart-form: %v", err)
- webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
- return
- }
- if username == "" {
- webUploadErrorResponse(w, http.StatusBadRequest, "missing field LOGIN_NAME")
- return
- }
- if sessionid == "" {
- webUploadErrorResponse(w, http.StatusBadRequest, "missing field SESSION_ID")
- return
- }
- if srcfile == "" || src == nil {
- webUploadErrorResponse(w, http.StatusBadRequest, "missing field FILENAME")
+ parts := strings.SplitN(r.URL.String(), "/", 2)
+ if len(parts) != 2 {
+ rhl.Printf("WebUploadHandler: got invalid request url")
+ webUploadErrorResponse(w, http.StatusBadRequest, "invalid request URL, should be <username>/<sessionid>")
return
}
+ username := parts[0]
+ sessionid := parts[1]
s, _, code, _ := sessions.Get(username, sessionid)
if code != http.StatusOK {
+ rhl.Printf("WebUploadHandler: refusing file upload for '%s/%s': session not found", username, sessionid)
webUploadErrorResponse(w, http.StatusUnauthorized, "session not found")
return
}
cancel, attachmentChan := s.AttachUploader()
if attachmentChan == nil || cancel == nil {
- rhl.Printf("WebUploadHandler: refusing file upload for '%s': session already uploading", srcfile)
+ rhl.Printf("WebUploadHandler: refusing file upload for '%s/%s': session already uploading", username, sessionid)
webUploadErrorResponse(w, http.StatusForbidden, "upload already in progress")
return
}
defer close(attachmentChan)
- rhl.Printf("WebUploadHandler: starting upload for file '%s'", srcfile)
+ rhl.Printf("WebUploadHandler: starting file upload for '%s/%s'", username, sessionid)
for {
chunk := rhimport.AttachmentChunk{}
var data [128 * 1024]byte
- n, err := src.Read(data[:])
+ n, err := r.Body.Read(data[:])
if n > 0 {
chunk.Data = data[:n]
if err == io.EOF {
@@ -165,14 +102,14 @@ func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
}
chunk.Error = err
if err == io.EOF {
- rhl.Printf("WebUploadHandler: upload for file '%s' finished", srcfile)
+ rhl.Printf("WebUploadHandler: file upload for '%s/%s' finished", username, sessionid)
webUploadSuccessResponse(w)
return
}
select {
case <-cancel:
- rhl.Printf("WebUploadHandler: upload for file '%s' got canceld", srcfile)
+ rhl.Printf("WebUploadHandler: file upload for '%s/%s' got canceld", username, sessionid)
webUploadErrorResponse(w, http.StatusNoContent, "canceled")
return
case attachmentChan <- chunk: