chore: fixes to paste ui
This commit is contained in:
		
							parent
							
								
									9a26239aa7
								
							
						
					
					
						commit
						62c01484db
					
				@ -1,13 +1,13 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "files": {
 | 
					  "files": {
 | 
				
			||||||
    "main.css": "/ui/static/css/main.d4025777.css",
 | 
					    "main.css": "/ui/static/css/main.d4025777.css",
 | 
				
			||||||
    "main.js": "/ui/static/js/main.1d06557a.js",
 | 
					    "main.js": "/ui/static/js/main.939bead5.js",
 | 
				
			||||||
    "index.html": "/ui/index.html",
 | 
					    "index.html": "/ui/index.html",
 | 
				
			||||||
    "main.d4025777.css.map": "/ui/static/css/main.d4025777.css.map",
 | 
					    "main.d4025777.css.map": "/ui/static/css/main.d4025777.css.map",
 | 
				
			||||||
    "main.1d06557a.js.map": "/ui/static/js/main.1d06557a.js.map"
 | 
					    "main.939bead5.js.map": "/ui/static/js/main.939bead5.js.map"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "entrypoints": [
 | 
					  "entrypoints": [
 | 
				
			||||||
    "static/css/main.d4025777.css",
 | 
					    "static/css/main.d4025777.css",
 | 
				
			||||||
    "static/js/main.1d06557a.js"
 | 
					    "static/js/main.939bead5.js"
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1 +1 @@
 | 
				
			|||||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/ui/manifest.json"><link rel="shortcut icon" href="/ui/favicon.ico"><title>DN42 Paste</title><script defer="defer" src="/ui/static/js/main.1d06557a.js"></script><link href="/ui/static/css/main.d4025777.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
 | 
					<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="#000000"><link rel="manifest" href="/ui/manifest.json"><link rel="shortcut icon" href="/ui/favicon.ico"><title>DN42 Paste</title><script defer="defer" src="/ui/static/js/main.939bead5.js"></script><link href="/ui/static/css/main.d4025777.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -200,17 +200,17 @@ class Paste extends Component {
 | 
				
			|||||||
  onSubmit(event) {
 | 
					  onSubmit(event) {
 | 
				
			||||||
    event.preventDefault();
 | 
					    event.preventDefault();
 | 
				
			||||||
    const { plain } = this.state;
 | 
					    const { plain } = this.state;
 | 
				
			||||||
    const { history } = this.props;
 | 
					    // const { history } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.encrypt(plain).then(([hash, decryptKey]) => { history.push('/#/' + hash + '!' + decryptKey) });
 | 
					    this.encrypt(plain).then(([hash, decryptKey]) => { history.pushState({}, '', '/ui/#/' + hash + '!' + decryptKey) });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  onNew(event) {
 | 
					  onNew(event) {
 | 
				
			||||||
    const { history } = this.props;
 | 
					    // const { history } = this.props;
 | 
				
			||||||
    this.setState({cipher:"", plain:"", hash: "", decryptKey: "", syntax: "text", expire: 604800, burn: false}, () => history.push('/'));
 | 
					    this.setState({cipher:"", plain:"", hash: "", decryptKey: "", syntax: "text", expire: 604800, burn: false}, () => history.pushState({}, '', '/ui'));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  onCopy(event) {
 | 
					  onCopy(event) {
 | 
				
			||||||
    const { history } = this.props;
 | 
					    // const { history } = this.props;
 | 
				
			||||||
    this.setState({hash: "", decryptKey: ""}, () => history.push('/'))
 | 
					    this.setState({hash: "", decryptKey: ""}, () => history.pushState({}, '', '/ui'))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  decrypt(tx) {
 | 
					  decrypt(tx) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@ -5,6 +5,7 @@ go 1.21
 | 
				
			|||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167
 | 
						github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167
 | 
				
			||||||
	github.com/h2non/filetype v1.1.0
 | 
						github.com/h2non/filetype v1.1.0
 | 
				
			||||||
 | 
						github.com/matryer/is v1.4.1
 | 
				
			||||||
	github.com/rs/cors v1.6.0
 | 
						github.com/rs/cors v1.6.0
 | 
				
			||||||
	go.opentelemetry.io/otel v1.18.0
 | 
						go.opentelemetry.io/otel v1.18.0
 | 
				
			||||||
	go.opentelemetry.io/otel/trace v1.18.0
 | 
						go.opentelemetry.io/otel/trace v1.18.0
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										137
									
								
								image/image.go
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								image/image.go
									
									
									
									
									
								
							@ -13,6 +13,7 @@ import (
 | 
				
			|||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/h2non/filetype"
 | 
						"github.com/h2non/filetype"
 | 
				
			||||||
	"go.opentelemetry.io/otel/attribute"
 | 
						"go.opentelemetry.io/otel/attribute"
 | 
				
			||||||
@ -58,63 +59,96 @@ func (a *image) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
	defer span.End()
 | 
						defer span.End()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch r.Method {
 | 
						switch r.Method {
 | 
				
			||||||
	case http.MethodGet:
 | 
						case http.MethodGet, http.MethodHead:
 | 
				
			||||||
		name := strings.TrimPrefix(r.URL.Path, "/")
 | 
							name := strings.TrimPrefix(r.URL.Path, "/")
 | 
				
			||||||
 | 
							if name != "" {
 | 
				
			||||||
		a.get(ctx, w, name)
 | 
								rdr, head, err := a.loadFile(ctx, name)
 | 
				
			||||||
	case http.MethodPost:
 | 
					 | 
				
			||||||
		var err error
 | 
					 | 
				
			||||||
		var fd io.ReadCloser = r.Body
 | 
					 | 
				
			||||||
		if r.URL.Path == "/3/upload" {
 | 
					 | 
				
			||||||
			fd, _, err = r.FormFile("image")
 | 
					 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				w.WriteHeader(http.StatusBadRequest)
 | 
									writeError(w, err)
 | 
				
			||||||
 | 
									span.RecordError(err)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								defer rdr.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								w.Header().Set("X-Content-Type-Options", "nosniff")
 | 
				
			||||||
 | 
								w.Header().Set("Content-Type", head.Mime)
 | 
				
			||||||
 | 
								w.Header().Set("ETag", head.ETag)
 | 
				
			||||||
 | 
								w.Header().Set("Last-Modified", head.Modified.Format(time.RFC850))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if r.Method == http.MethodHead {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								http.ServeContent(w, r, "", head.Modified, rdr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
 | 
						case http.MethodPost:
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							defer r.Body.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var fd io.ReadCloser = r.Body
 | 
				
			||||||
 | 
							if r.URL.Path == "/3/upload" {
 | 
				
			||||||
 | 
								span.AddEvent("Imgur Emulation")
 | 
				
			||||||
 | 
								if data := r.FormValue("image"); data != "" {
 | 
				
			||||||
 | 
									var rdr io.Reader = strings.NewReader(data)
 | 
				
			||||||
 | 
									if t := r.FormValue("type"); t == "base64" {
 | 
				
			||||||
 | 
										rdr = base64.NewDecoder(base64.StdEncoding, rdr)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									fd = io.NopCloser(rdr)
 | 
				
			||||||
 | 
								} else if fd, _, err = r.FormFile("image"); err != nil {
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										span.RecordError(err)
 | 
				
			||||||
 | 
										w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									defer fd.Close()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusCreated)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		length := 0
 | 
							length := 0
 | 
				
			||||||
		if h := r.Header.Get("Content-Length"); h != "" {
 | 
							if h := r.Header.Get("Content-Length"); h != "" {
 | 
				
			||||||
			if i, err := strconv.Atoi(h); err != nil {
 | 
								if i, err := strconv.Atoi(h); err != nil {
 | 
				
			||||||
				length = i
 | 
									length = i
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		id, err := a.put(ctx, w, fd, length)
 | 
							id, err := a.put(ctx, fd, length)
 | 
				
			||||||
		switch {
 | 
							if err != nil {
 | 
				
			||||||
		case errors.Is(err, ErrGone):
 | 
								writeError(w, err)
 | 
				
			||||||
			w.WriteHeader(http.StatusGone)
 | 
								span.RecordError(err)
 | 
				
			||||||
		case errors.Is(err, ErrNotFound):
 | 
								return
 | 
				
			||||||
			w.WriteHeader(http.StatusNotFound)
 | 
					 | 
				
			||||||
		case errors.Is(err, ErrReadingContent):
 | 
					 | 
				
			||||||
			w.WriteHeader(http.StatusInternalServerError)
 | 
					 | 
				
			||||||
		case errors.Is(err, ErrUnsupportedType):
 | 
					 | 
				
			||||||
			w.WriteHeader(http.StatusUnsupportedMediaType)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		type data struct{
 | 
							type data struct {
 | 
				
			||||||
			Link string `json:"link"`
 | 
								Link       string `json:"link"`
 | 
				
			||||||
			DeleteHash string `json:"deletehash"`
 | 
								DeleteHash string `json:"deletehash"`
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		var resp = struct{
 | 
							var resp = struct {
 | 
				
			||||||
			Data data `json:"data"`
 | 
								Data    data `json:"data"`
 | 
				
			||||||
			Success bool `json:"success"`
 | 
								Success bool `json:"success"`
 | 
				
			||||||
			Status int `json:"status"`
 | 
								Status  int  `json:"status"`
 | 
				
			||||||
		}{
 | 
							}{
 | 
				
			||||||
			Data: data{
 | 
								Data: data{
 | 
				
			||||||
				Link: fmt.Sprintf("https://%s/i/%s", r.Host, id),
 | 
									Link: fmt.Sprintf("https://%s/i/%s", r.Host, id),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Success: true,
 | 
								Success: true,
 | 
				
			||||||
			Status: 200,
 | 
								Status:  200,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		json.NewEncoder(w).Encode(resp)
 | 
							err = json.NewEncoder(w).Encode(resp)
 | 
				
			||||||
 | 
							span.RecordError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
 | 
							http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *image) get(ctx context.Context, w http.ResponseWriter, name string) error {
 | 
					func (a *image) loadFile(ctx context.Context, name string) (io.ReadSeekCloser, *Header, error) {
 | 
				
			||||||
	_, span := lg.Span(ctx)
 | 
						_, span := lg.Span(ctx)
 | 
				
			||||||
	defer span.End()
 | 
						defer span.End()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,38 +158,42 @@ func (a *image) get(ctx context.Context, w http.ResponseWriter, name string) err
 | 
				
			|||||||
	fname := filepath.Join(a.store, id)
 | 
						fname := filepath.Join(a.store, id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !chkFile(fname) {
 | 
						if !chkFile(fname) {
 | 
				
			||||||
		return fmt.Errorf("%w: %s", ErrNotFound, fname)
 | 
							return nil, nil, fmt.Errorf("%w: %s", ErrNotFound, fname)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if chkGone(fname) {
 | 
						if chkGone(fname) {
 | 
				
			||||||
		return fmt.Errorf("%w: %s", ErrGone, fname)
 | 
							return nil, nil, fmt.Errorf("%w: %s", ErrGone, fname)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f, err := os.Open(fname)
 | 
						f, err := os.Open(fname)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return nil, nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stat, err := f.Stat()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer f.Close()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr := readutil.NewPreviewReader(f)
 | 
						pr := readutil.NewPreviewReader(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mime, err := readutil.ReadMIME(pr, name)
 | 
						mime, err := readutil.ReadMIME(pr, name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return nil, nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	w.Header().Set("Content-Type", mime)
 | 
					 | 
				
			||||||
	w.Header().Set("X-Content-Type-Options", "nosniff")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, _ = io.Copy(w, pr.Drain())
 | 
						return f,
 | 
				
			||||||
	return nil
 | 
							&Header{Mime: mime, Modified: stat.ModTime(), ETag: name},
 | 
				
			||||||
 | 
							nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (a *image) put(ctx context.Context, w http.ResponseWriter, r io.ReadCloser, length int) (string, error) {
 | 
					func (a *image) put(ctx context.Context, r io.ReadCloser, length int) (string, error) {
 | 
				
			||||||
	_, span := lg.Span(ctx)
 | 
						_, span := lg.Span(ctx)
 | 
				
			||||||
	defer span.End()
 | 
						defer span.End()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer r.Close()
 | 
						defer r.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						span.AddEvent("content length", trace.WithAttributes(attribute.Int64("max-size", a.maxSize), attribute.Int("length", length)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if length > 0 {
 | 
						if length > 0 {
 | 
				
			||||||
		if int64(length) > a.maxSize {
 | 
							if int64(length) > a.maxSize {
 | 
				
			||||||
			return "", ErrSizeTooLarge
 | 
								return "", ErrSizeTooLarge
 | 
				
			||||||
@ -165,6 +203,7 @@ func (a *image) put(ctx context.Context, w http.ResponseWriter, r io.ReadCloser,
 | 
				
			|||||||
	rdr := io.LimitReader(r, a.maxSize)
 | 
						rdr := io.LimitReader(r, a.maxSize)
 | 
				
			||||||
	pr := readutil.NewPreviewReader(rdr)
 | 
						pr := readutil.NewPreviewReader(rdr)
 | 
				
			||||||
	if !isImageOrVideo(pr) {
 | 
						if !isImageOrVideo(pr) {
 | 
				
			||||||
 | 
							span.AddEvent("not image")
 | 
				
			||||||
		return "", ErrUnsupportedType
 | 
							return "", ErrUnsupportedType
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rdr = pr.Drain()
 | 
						rdr = pr.Drain()
 | 
				
			||||||
@ -172,6 +211,7 @@ func (a *image) put(ctx context.Context, w http.ResponseWriter, r io.ReadCloser,
 | 
				
			|||||||
	s256 := sha256.New()
 | 
						s256 := sha256.New()
 | 
				
			||||||
	tmp, err := os.CreateTemp(a.store, "image-")
 | 
						tmp, err := os.CreateTemp(a.store, "image-")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							span.RecordError(err)
 | 
				
			||||||
		return "", fmt.Errorf("%w: %w", ErrBadInput, err)
 | 
							return "", fmt.Errorf("%w: %w", ErrBadInput, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -179,6 +219,7 @@ func (a *image) put(ctx context.Context, w http.ResponseWriter, r io.ReadCloser,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	m := io.MultiWriter(s256, tmp)
 | 
						m := io.MultiWriter(s256, tmp)
 | 
				
			||||||
	if _, err := io.Copy(m, rdr); err != nil {
 | 
						if _, err := io.Copy(m, rdr); err != nil {
 | 
				
			||||||
 | 
							span.RecordError(err)
 | 
				
			||||||
		return "", fmt.Errorf("%w: %w", ErrBadInput, err)
 | 
							return "", fmt.Errorf("%w: %w", ErrBadInput, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tmp.Close()
 | 
						tmp.Close()
 | 
				
			||||||
@ -186,7 +227,7 @@ func (a *image) put(ctx context.Context, w http.ResponseWriter, r io.ReadCloser,
 | 
				
			|||||||
	id := base64.RawURLEncoding.EncodeToString(s256.Sum(nil)[12:])
 | 
						id := base64.RawURLEncoding.EncodeToString(s256.Sum(nil)[12:])
 | 
				
			||||||
	fname := filepath.Join(a.store, id)
 | 
						fname := filepath.Join(a.store, id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	span.AddEvent("image: moving file", trace.WithAttributes(attribute.String("src", tmp.Name()), attribute.String("dst", fname)))
 | 
						span.AddEvent("image: moving file", trace.WithAttributes(attribute.String("image-src", tmp.Name()), attribute.String("image-dst", fname)))
 | 
				
			||||||
	_ = os.Rename(tmp.Name(), fname)
 | 
						_ = os.Rename(tmp.Name(), fname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return id, nil
 | 
						return id, nil
 | 
				
			||||||
@ -255,6 +296,24 @@ func chkGone(path string) bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					func writeError(w http.ResponseWriter, err error) {
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case errors.Is(err, ErrGone):
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusGone)
 | 
				
			||||||
 | 
						case errors.Is(err, ErrNotFound):
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
						case errors.Is(err, ErrReadingContent):
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
						case errors.Is(err, ErrUnsupportedType):
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusUnsupportedMediaType)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Header struct {
 | 
				
			||||||
 | 
						Mime     string
 | 
				
			||||||
 | 
						Modified time.Time
 | 
				
			||||||
 | 
						ETag     string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	ErrNotFound        = errors.New("not found")
 | 
						ErrNotFound        = errors.New("not found")
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										114
									
								
								image/image_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								image/image_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					package image_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"mime/multipart"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/http/httptest"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/matryer/is"
 | 
				
			||||||
 | 
						"go.sour.is/paste/v2/image"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var testImage = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z/C/HgAGgwJ/lK3Q6wAAAABJRU5ErkJggg=="
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPostImgur(t *testing.T) {
 | 
				
			||||||
 | 
						is := is.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dir, err := os.MkdirTemp("", "image")
 | 
				
			||||||
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						im, err := image.New(dir, 0)
 | 
				
			||||||
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							body := &bytes.Buffer{}
 | 
				
			||||||
 | 
							wr := multipart.NewWriter(body)
 | 
				
			||||||
 | 
							w, err := wr.CreateFormField("type")
 | 
				
			||||||
 | 
							is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Fprint(w, "base64")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							w, err = wr.CreateFormField("image")
 | 
				
			||||||
 | 
							is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Fprint(w, testImage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = wr.Close()
 | 
				
			||||||
 | 
							is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							t.Log(body.String())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							req := httptest.NewRequest("POST", "/3/upload", body)
 | 
				
			||||||
 | 
							req.Header.Set("Content-Type", "multipart/form-data; boundary="+wr.Boundary())
 | 
				
			||||||
 | 
							res := httptest.NewRecorder()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							im.ServeHTTP(res, req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							is.Equal(res.Code, http.StatusOK)
 | 
				
			||||||
 | 
							is.Equal(res.Body.String(), `{"data":{"link":"https://example.com/i/Igg59VTi6JNuXVriXMR3U_lzfAc","deletehash":""},"success":true,"status":200}
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							req := httptest.NewRequest("GET", "/Igg59VTi6JNuXVriXMR3U_lzfAc", nil)
 | 
				
			||||||
 | 
							res := httptest.NewRecorder()
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							im.ServeHTTP(res, req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							is.Equal(res.Code, http.StatusOK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							s := base64.StdEncoding.EncodeToString(res.Body.Bytes())
 | 
				
			||||||
 | 
							is.Equal(s, testImage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = os.RemoveAll(dir)
 | 
				
			||||||
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPost(t *testing.T) {
 | 
				
			||||||
 | 
						is := is.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dir, err := os.MkdirTemp("", "image")
 | 
				
			||||||
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						im, err := image.New(dir, 0)
 | 
				
			||||||
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							req := httptest.NewRequest("POST", "/i", base64.NewDecoder(base64.StdEncoding, strings.NewReader(testImage)))
 | 
				
			||||||
 | 
							res := httptest.NewRecorder()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							im.ServeHTTP(res, req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							is.Equal(res.Code, http.StatusCreated)
 | 
				
			||||||
 | 
							is.Equal(res.Body.String(), `{"data":{"link":"https://example.com/i/Igg59VTi6JNuXVriXMR3U_lzfAc","deletehash":""},"success":true,"status":200}
 | 
				
			||||||
 | 
					`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							req := httptest.NewRequest("GET", "/Igg59VTi6JNuXVriXMR3U_lzfAc", nil)
 | 
				
			||||||
 | 
							res := httptest.NewRecorder()
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							im.ServeHTTP(res, req)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							is.Equal(res.Code, http.StatusOK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							s := base64.StdEncoding.EncodeToString(res.Body.Bytes())
 | 
				
			||||||
 | 
							is.Equal(s, testImage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = os.RemoveAll(dir)
 | 
				
			||||||
 | 
						is.NoErr(err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -20,12 +20,13 @@ var _ = apps.Register(20, func(ctx context.Context, svc *service.Harness) error
 | 
				
			|||||||
	svc.Add(s)
 | 
						svc.Add(s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mux := mux.New()
 | 
						mux := mux.New()
 | 
				
			||||||
	s.Handler = cors.AllowAll().Handler(mux)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s.Handler = mux
 | 
				
			||||||
	s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
						s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
		log.Println(r.Method, r.URL.Path)
 | 
							log.Println(r.Method, r.URL.Path)
 | 
				
			||||||
		mux.ServeHTTP(w, r)
 | 
							mux.ServeHTTP(w, r)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						s.Handler = cors.AllowAll().Handler(s.Handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s.Addr = env.Default("HTTP_LISTEN", ":8080")
 | 
						s.Addr = env.Default("HTTP_LISTEN", ":8080")
 | 
				
			||||||
	if strings.HasPrefix(s.Addr, ":") {
 | 
						if strings.HasPrefix(s.Addr, ":") {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user