| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- package web
- import (
- "bytes"
- "encoding/base64"
- "io"
- "mime/multipart"
- "net/http"
- p "github.com/ajswis/go-pkparse-server/pokemon"
- pokemonparsing "github.com/ajswis/go-pkparse-server/pokemon-parsing"
- "github.com/gin-gonic/gin"
- )
- /*
- File uploads:
- curl -X POST http://localhost:8080/parse \
- -H "Content-Type: multipart/form-data" \
- --form "pokemon=@/path/to/test/file1" \
- --form "pokemon=@/path/to/test/file2"
- JSON POST:
- curl -X POST http://localhost:8080/parse \
- -H "Content-Type: application/json" \
- -d '{"pokemon": ["base64_encoded_pokemon_file", "another_base64_encoded_pokemon_file"]}'
- Form POST:
- curl -X POST http://localhost:8080/parse \
- -H "Content-Type: multipart/form-data" \
- --form 'pokemon=base64_encoded_pokemon_file' \
- --form 'pokemon=another_base64_encoded_pokemon_file'
- Form POST + File upload:
- curl -X POST http://localhost:8080/parse \
- -H "Content-Type: multipart/form-data" \
- --form "pokemon=@/path/to/test/file1" \
- --form "pokemon=@/path/to/test/file2" \
- --form 'pokemon=base64_encoded_pokemon_file' \
- */
- type pokemonParseRequest struct {
- Pokemon []string `json:"pokemon" form:"pokemon"`
- }
- // parse grabs multipart file uploads under the key `pokemon`, aggregates them,
- // and delegates work to the parser.
- func (s *Server) parse(c *gin.Context) {
- var rawPokemon []p.RawPokemon
- // If the POST is `multipart/form-data`, check for file uploads and read them
- if c.ContentType() == "multipart/form-data" {
- fileHeaders, err := uploadedPokemonFiles(c)
- if err != nil {
- render(c, http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- if len(fileHeaders) > 0 {
- err = pokemonFromFileUpload(fileHeaders, &rawPokemon)
- if err != nil {
- render(c, http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- }
- }
- // For non-file-upload form submissions or all other `Content-Type`s
- err := pokemonFromEncodedUpload(c, &rawPokemon)
- if err != nil {
- render(c, http.StatusInternalServerError, gin.H{"error": err.Error()})
- return
- }
- pkmn, err := pokemonparsing.ParseAll(rawPokemon)
- if err != nil {
- render(c, http.StatusUnprocessableEntity, gin.H{"error": err.Error()})
- return
- }
- render(c, http.StatusOK, pkmn)
- }
- // uploadedPokemonFiles extracts any existing FileHeaders from file uploads
- func uploadedPokemonFiles(c *gin.Context) ([]*multipart.FileHeader, error) {
- form, err := c.MultipartForm()
- if err != nil {
- return nil, err
- }
- return form.File["pokemon"], nil
- }
- // pokemonFromFileUpload reads data from uploaded files and returns the raw
- // pokemon
- func pokemonFromFileUpload(files []*multipart.FileHeader, rawPokemon *[]p.RawPokemon) error {
- for _, file := range files {
- var err error
- var src multipart.File
- src, err = file.Open()
- if err != nil {
- return err
- }
- defer src.Close()
- buf := bytes.NewBuffer(nil)
- if _, err = io.Copy(buf, src); err != nil {
- return err
- }
- *rawPokemon = append(*rawPokemon, buf.Bytes())
- }
- return nil
- }
- // pokemonFromEncodedUpload binds the POST data to a `pokemonParseRequest` and
- // converts each base64 string to a `[]byte` slice.
- func pokemonFromEncodedUpload(c *gin.Context, rawPokemon *[]p.RawPokemon) error {
- var request pokemonParseRequest
- if err := c.ShouldBind(&request); err != nil {
- return err
- }
- for _, pkmn := range request.Pokemon {
- var err error
- var decoded []byte
- decoded, err = base64.StdEncoding.DecodeString(pkmn)
- if err != nil {
- return err
- }
- *rawPokemon = append(*rawPokemon, decoded)
- }
- return nil
- }
|