summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@helsinki.at>2016-07-22 16:42:07 (GMT)
committerChristian Pointner <equinox@helsinki.at>2016-07-22 16:42:07 (GMT)
commita4588ab0c505b79caf8858cac06a9b8fb58ac81c (patch)
tree6768091dfef1537b8d99646c66c11741c9514981
parent34d536887eeb88e7b3d407a31332a13bb0bff5f5 (diff)
new uploadWeb mostly done
-rw-r--r--src/rhimportd/ctrlWebSocket.go18
-rw-r--r--src/rhimportd/uploadWeb.go72
-rw-r--r--web-static/upload-form.html2
3 files changed, 63 insertions, 29 deletions
diff --git a/src/rhimportd/ctrlWebSocket.go b/src/rhimportd/ctrlWebSocket.go
index e764085..1ce0f80 100644
--- a/src/rhimportd/ctrlWebSocket.go
+++ b/src/rhimportd/ctrlWebSocket.go
@@ -25,17 +25,18 @@
package main
import (
- "code.helsinki.at/rhrd-go/rddb"
- "code.helsinki.at/rhrd-go/rhimport"
"encoding/json"
"fmt"
- "github.com/gorilla/websocket"
"html"
"io"
"io/ioutil"
"math"
"net/http"
"time"
+
+ "code.helsinki.at/rhrd-go/rddb"
+ "code.helsinki.at/rhrd-go/rhimport"
+ "github.com/gorilla/websocket"
)
type webSocketRequestData struct {
@@ -224,7 +225,7 @@ func webSocketDone(res rhimport.Result, userdata interface{}) bool {
return true
}
-func (self *webSocketSession) startNewSession(reqdata *webSocketRequestData, binchan <-chan []byte, conf *rhimport.Config, sessions *rhimport.SessionStoreChan) (int, string) {
+func (self *webSocketSession) startNewSession(reqdata *webSocketRequestData, conf *rhimport.Config, sessions *rhimport.SessionStoreChan) (int, string) {
ctx := rhimport.NewContext(conf, nil)
ctx.UserName = reqdata.UserName
ctx.Password = reqdata.Password
@@ -240,7 +241,6 @@ func (self *webSocketSession) startNewSession(reqdata *webSocketRequestData, bin
ctx.AutotrimLevel = reqdata.AutotrimLevel
ctx.UseMetaData = reqdata.UseMetaData
ctx.SourceUri = reqdata.SourceUri
- ctx.AttachmentChan = binchan
id, s, code, errstring := sessions.New(ctx, reqdata.RefId)
if code != http.StatusOK {
@@ -302,7 +302,7 @@ func webSocketListUpdate(added, removed map[string]string, userdata interface{})
return true
}
-func webSocketSessionHandler(reqchan <-chan webSocketRequestData, binchan <-chan []byte, ws *websocket.Conn, conf *rhimport.Config, sessions *rhimport.SessionStoreChan) {
+func webSocketSessionHandler(reqchan <-chan webSocketRequestData, ws *websocket.Conn, conf *rhimport.Config, sessions *rhimport.SessionStoreChan) {
defer ws.Close()
closed := make(chan bool, 1)
@@ -325,7 +325,7 @@ func webSocketSessionHandler(reqchan <-chan webSocketRequestData, binchan <-chan
if session.id != "" {
sendWebSocketErrorResponse(ws, http.StatusBadRequest, "This connection already handles a session")
} else {
- code, errstring := session.startNewSession(&reqdata, binchan, conf, sessions)
+ code, errstring := session.startNewSession(&reqdata, conf, sessions)
if code != http.StatusOK {
sendWebSocketErrorResponse(ws, code, errstring)
} else {
@@ -389,10 +389,8 @@ func webSocketHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
}
rhdl.Println("WebSocket Client", ws.RemoteAddr(), "connected")
reqchan := make(chan webSocketRequestData)
- binchan := make(chan []byte)
- go webSocketSessionHandler(reqchan, binchan, ws, conf, sessions)
+ go webSocketSessionHandler(reqchan, ws, conf, sessions)
defer close(reqchan)
- defer close(binchan)
for {
t, r, err := ws.NextReader()
diff --git a/src/rhimportd/uploadWeb.go b/src/rhimportd/uploadWeb.go
index 412df12..224e91d 100644
--- a/src/rhimportd/uploadWeb.go
+++ b/src/rhimportd/uploadWeb.go
@@ -27,9 +27,7 @@ package main
import (
"bytes"
"encoding/json"
- "fmt"
"io"
- "io/ioutil"
"mime/multipart"
"net/http"
@@ -62,7 +60,7 @@ const (
webUploadMaxRequestSize = (2 << 30) - 1 // 2GB, (2 << 30) overflows int on 32-bit systems therefore we use 2GB - 1 Byte
)
-func webUploadParseForm(w http.ResponseWriter, r *http.Request) (username, sessionid, srcfile string, src *multipart.Part, ok bool) {
+func webUploadParseForm(w http.ResponseWriter, r *http.Request) (username, sessionid, srcfile string, src *multipart.Part) {
mpr, err := r.MultipartReader()
if err != nil {
rhl.Printf("WebUploadHandler: error while parsing multipart-form: %v", err)
@@ -72,6 +70,9 @@ func webUploadParseForm(w http.ResponseWriter, r *http.Request) (username, sessi
for {
p, err := mpr.NextPart()
+ if err == io.EOF {
+ return
+ }
if err != nil {
rhl.Printf("WebUploadHandler: error while parsing multipart-form: %v", err)
webUploadErrorResponse(w, http.StatusBadRequest, err.Error())
@@ -86,12 +87,10 @@ func webUploadParseForm(w http.ResponseWriter, r *http.Request) (username, sessi
case "FILENAME":
srcfile = p.FileName()
src = p
- ok = true
- return
+ return // don't read any fileds beyond this point because we would need to load the whole file in order to continue parsing
default:
- rhl.Printf("WebUploadHandler: unknown form field: '%s'", p.FormName())
- webUploadErrorResponse(w, http.StatusBadRequest, fmt.Sprintf("unknown field %s", p.FormName()))
- return
+ rhdl.Printf("WebUploadHandler: ingoring unknown form field: '%s'", p.FormName())
+ continue
}
var buf bytes.Buffer
@@ -125,10 +124,7 @@ func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
}
r.Body = http.MaxBytesReader(w, r.Body, webUploadMaxRequestSize)
- username, sessionid, srcfile, src, ok := webUploadParseForm(w, r)
- if !ok {
- return
- }
+ username, sessionid, srcfile, src := webUploadParseForm(w, r)
if username == "" {
webUploadErrorResponse(w, http.StatusBadRequest, "missing field LOGIN_NAME")
return
@@ -137,13 +133,53 @@ func webUploadHandler(conf *rhimport.Config, db *rddb.DBChan, sessions *rhimport
webUploadErrorResponse(w, http.StatusBadRequest, "missing field SESSION_ID")
return
}
+ if srcfile == "" || src == nil {
+ webUploadErrorResponse(w, http.StatusBadRequest, "missing field FILENAME")
+ return
+ }
+
+ s, _, code, _ := sessions.Get(username, sessionid)
+ if code != http.StatusOK {
+ webUploadErrorResponse(w, http.StatusUnauthorized, "session not found")
+ return
+ }
+
+ cancel, attachmentChan := s.AttachUploader()
+ if attachmentChan == nil || cancel == nil {
+ webUploadErrorResponse(w, http.StatusForbidden, "upload already in progress")
+ return
+ }
+ defer close(attachmentChan)
- // TODO: get session->attachmentChan from store -> 401 if not found
- // TODO: take session -> 403 if already taken
+ rhl.Printf("WebUploadHandler: starting upload for file '%s'", srcfile)
+ for {
+ chunk := rhimport.AttachmentChunk{}
+
+ var data [128 * 1024]byte
+ n, err := src.Read(data[:])
+ if n > 0 {
+ chunk.Data = data[:n]
+ if err == io.EOF {
+ err = nil
+ }
+ }
+ chunk.Error = err
+ if err == io.EOF {
+ webUploadSuccessResponse(w)
+ return
+ }
- // TODO: fetch file (src) in chunks and send it to attachmentChan && check for canceled
- rhl.Printf("WebUploadHandler: fetching file from '%s' (%v)", srcfile, src)
- io.Copy(ioutil.Discard, src)
+ select {
+ case <-cancel:
+ rhl.Printf("WebUploadHandler: upload for file '%s' got canceld", srcfile)
+ webUploadErrorResponse(w, http.StatusNoContent, "canceled")
+ return
+ case attachmentChan <- chunk:
+ }
- webUploadSuccessResponse(w)
+ if err != nil {
+ webUploadErrorResponse(w, http.StatusInternalServerError, err.Error())
+ return
+ }
+ }
}
diff --git a/web-static/upload-form.html b/web-static/upload-form.html
index c38037e..5353f95 100644
--- a/web-static/upload-form.html
+++ b/web-static/upload-form.html
@@ -19,7 +19,7 @@
<form class="form-upload" method="post" action="/public/upload" enctype="multipart/form-data">
<table>
<tr><td class="label">Username</td><td><input type="text" name="LOGIN_NAME" size="20" value="heslinki" /></td></tr>
- <tr><td class="label">Session</td><td><input type="password" name="SESSION_ID" size="20" /></td></tr>
+ <tr><td class="label">Session</td><td><input type="text" name="SESSION_ID" size="45" /></td></tr>
<tr><td class="label">File</td><td><input type="file" name="FILENAME" /></td></tr>
<tr><td>&nbsp;</td><td><input type="submit" name="submit" value="Submit"></td></tr>
</table>