Skip to content

Commit

Permalink
improve docs
Browse files Browse the repository at this point in the history
  • Loading branch information
adelowo committed Feb 24, 2024
1 parent 290730e commit 9b6b6c3
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 21 deletions.
68 changes: 58 additions & 10 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,21 +1,57 @@
# Gulter

Gulter is a Go HTTP middleware designed to simplify the process of uploading files for your web apps. It follows the standard
`http.Handler` and `http.HandlerFunc` interfaces so you can always use with any of framework or the standard library router.
Gulter is a Go HTTP middleware designed to simplify the process of uploading files
for your web apps. It follows the standard
`http.Handler` and `http.HandlerFunc` interfaces so you can
always use with any of framework or the standard library router.

> Name and idea was gotten from the insanely popular multer package in Node.JS that does the same.
> Name and idea was gotten from the insanely popular multer package
> in Node.JS that does the same.
### Installation
## Installation

```go

go get -u -v github.com/adelowo/gulter

```

### Usage
## Usage

#### Standard HTTP router
Assuming you have a HTML form like this:

```html

<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="form-field-1" />
<input type="file" name="form-field-2" />
</form>

```

To create a new Gulter instance, you can do something like this:

```go
handler, _ := gulter.New(
gulter.WithMaxFileSize(10<<20),
gulter.WithValidationFunc(
gulter.ChainValidators(gulter.MimeTypeValidator("image/jpeg", "image/png"),
func(f gulter.File) error {
// Your own custom validation function on the file here
// Else you can really just drop the ChainValidators and use only the MimeTypeValidator or just
// one custom validator alone
return nil
})),
gulter.WithStorage(s3Store),
)
```

The `handler` is really just a HTTP middleware with the following signature
`Upload(keys ...string) func(next http.Handler) http.Handler`. `keys` here
are the input names from the HTML form, so you can chain this into almost any HTTP
router,

### Standard HTTP router

```go
package main
Expand All @@ -38,7 +74,7 @@ func main() {

// diskStore,err := storage.NewDiskStorage("/Users/lanreadelowo/gulter-uploads/")

handler := gulter.New(
handler, err := gulter.New(
gulter.WithMaxFileSize(10<<20),
gulter.WithStorage(s3Store),
)
Expand Down Expand Up @@ -73,9 +109,7 @@ func main() {

```
#### Chi router and other compatible HTTP handlers
### Chi router and other compatible HTTP handlers
```go

Expand Down Expand Up @@ -122,3 +156,17 @@ func main() {

```
## API
While this middleware automatically uploads your files, sometimes you need
details about the uploaded file to show to the user, this could be making up the
image url or path to the image. To get that in your HTTP handler, you can use either:
- `FileFromContext`: retrieve a named input uploaded file.
- `FilesFromContext`: retrieve all uploaded files
Gulter also ships with two storage implementations at the moment:
- `S3Store` : supports S3 or any compatible service like Minio
- `DiskStore`: uses a local filesystem backed store to upload files
12 changes: 10 additions & 2 deletions _examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ func main() {

// diskStore,err := storage.NewDiskStorage("/Users/lanreadelowo/gulter-uploads/")

handler := gulter.New(
// do not ignore :))
handler, _ := gulter.New(
gulter.WithMaxFileSize(10<<20),
// gulter.WithValidationFunc(gulter.ChainValidators(gulter.MimeTypeValidator("image/jpeg"))),
gulter.WithValidationFunc(
gulter.ChainValidators(gulter.MimeTypeValidator("image/jpeg", "image/png"),
func(f gulter.File) error {
// Your own custom validation function on the file here
// Else you can really just drop the ChainValidators and use only the MimeTypeValidator or just
// one custom validator alone
return nil
})),
gulter.WithStorage(s3Store),
)

Expand Down
6 changes: 0 additions & 6 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ func WithStorage(store Storage) Option {
}
}

func WithDestination(p string) Option {
return func(gh *Gulter) {
gh.destination = p
}
}

func WithMaxFileSize(i int64) Option {
return func(gh *Gulter) {
gh.maxSize = i
Expand Down
12 changes: 9 additions & 3 deletions handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gulter

import (
"errors"
"fmt"
"io"
"net/http"
Expand Down Expand Up @@ -42,15 +43,14 @@ type NameGeneratorFunc func(s string) string

type Gulter struct {
storage Storage
destination string
maxSize int64
formKeys []string
validationFunc ValidationFunc
nameFuncGenerator NameGeneratorFunc
errorResponseHandler ErrResponseHandler
}

func New(opts ...Option) *Gulter {
func New(opts ...Option) (*Gulter, error) {
handler := &Gulter{}

for _, opt := range opts {
Expand All @@ -73,9 +73,15 @@ func New(opts ...Option) *Gulter {
handler.errorResponseHandler = defaultErrorResponseHandler
}

return handler
if handler.storage == nil {
return nil, errors.New("you must provide a storage backend")
}

return handler, nil
}

// Upload is a HTTP middleware that takes in a list of form fields and the next
// HTTP handler to run after the upload prodcess is completed
func (h *Gulter) Upload(keys ...string) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down

0 comments on commit 9b6b6c3

Please sign in to comment.