summaryrefslogtreecommitdiff
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
parent2f2d09ea5aa99f1c80b12fc4e088ffc2248d690b (diff)
greatly simplified web uploads
-rw-r--r--src/rhimportd/routeWeb.go2
-rw-r--r--src/rhimportd/uploadWeb.go93
-rw-r--r--web-static/socket.html4
-rw-r--r--web-static/upload.html11
4 files changed, 22 insertions, 88 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:
diff --git a/web-static/socket.html b/web-static/socket.html
index 9781e81..6d6236c 100644
--- a/web-static/socket.html
+++ b/web-static/socket.html
@@ -66,8 +66,10 @@
$('#rawmsg').text("");
this.sock = new WebSocket("ws://localhost:4080/public/socket");
this.sock_onmessage = function (event) {
- $('#rawmsg').append(event.data + "\n");
msg = $.parseJSON(event.data)
+ if (msg.TYPE != "progress") {
+ $('#rawmsg').append(event.data + "<br />\n");
+ }
switch (msg.TYPE) {
case "ack":
$('#sessionid').val(msg.ID);
diff --git a/web-static/upload.html b/web-static/upload.html
index 39cfa57..21d1c48 100644
--- a/web-static/upload.html
+++ b/web-static/upload.html
@@ -26,21 +26,16 @@
function upload() {
$('#buttonupload').attr('disabled','disabled');
- var cmdData = new FormData();
- cmdData.append("LOGIN_NAME", $('#username').val());
- cmdData.append("SESSION_ID", $('#sessionid').val());
- cmdData.append("FILENAME", $('#file').get(0).files[0]);
var command = {
type: "POST",
- contentType: false,
+ contentType: "application/octet-stream",
+ data: $('#file').get(0).files[0],
processData: false,
- data: cmdData,
dataType: 'json',
error: function(req, status, err) { result({StatusText: status, ErrorString: err}); },
success: function(data, status, req) { result(data); }
};
- $.ajax('/public/upload', command);
-
+ $.ajax('/public/upload/' + $('#username').val() + '/' + $('#sessionid').val(), command);
}
function result(data) {