{"id":18023624,"url":"https://github.com/jeffotoni/goapigateway","last_synced_at":"2025-04-04T18:21:47.671Z","repository":{"id":134047232,"uuid":"87707113","full_name":"jeffotoni/goapigateway","owner":"jeffotoni","description":"This program aims to test the possibilities of file uploads ie uploads using the aws api-gateway in order to validate several ways to send files to a server using the api-gateway. Our goal is to discover the different ways of uploading and receiving upload so that we can implement our file server.","archived":false,"fork":false,"pushed_at":"2017-04-17T16:50:41.000Z","size":335,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-10T03:29:17.442Z","etag":null,"topics":["aws-apigateway","golang","golang-server","http-server","rest","rest-api","restful","ssl","upload","upload-file"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeffotoni.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-09T12:34:30.000Z","updated_at":"2018-12-22T11:50:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"8084e752-8631-4786-a320-626f85ebc4af","html_url":"https://github.com/jeffotoni/goapigateway","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffotoni%2Fgoapigateway","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffotoni%2Fgoapigateway/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffotoni%2Fgoapigateway/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffotoni%2Fgoapigateway/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeffotoni","download_url":"https://codeload.github.com/jeffotoni/goapigateway/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247226369,"owners_count":20904501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-apigateway","golang","golang-server","http-server","rest","rest-api","restful","ssl","upload","upload-file"],"created_at":"2024-10-30T07:10:02.679Z","updated_at":"2025-04-04T18:21:47.651Z","avatar_url":"https://github.com/jeffotoni.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# goapigateway\n\nThis program is a restful server, its purpose is to receive multiple POST requests, GET so that we can test the various ways to send files to a restful server. Our goal is to discover the different ways upload and receive upload so that we can implement our file server.\n\nThe Amazon is allowed to send binaries to its Api Gateway, and it is possible to use lambda functions so that the entire upload process is done by the Api Gateway without necessarily needing to send direct to a restful server, but our goal is to send direct to our server Restful\n\nWe will use curl as our client to test our submissions and we will also use the Amazon Api Gateway and see if it is possible to send a binary to our restful server directly without using lambda functions.\n\nEach test can be automated, but at the beginning for didactic reasons we will do the entire process manual so that we can fully understand its operation.\n\n## Used libraries:\n- https://github.com/gorilla/mux - Implements a request router and dispatcher for matching incoming requests\n- https://github.com/fatih/color - Help define the colors in the terminal\n\n\n## http.ListenAndServe\n\nIn golang everything becomes simpler, check the call to go up the door of our rest server, using http protocol\n\n```\nNative\nhttp.ListenAndServe(\":8080\", nil)\n\nUsing Mux\nconfServerHttpTest.ListenAndServe()\n\n```\n\nTo upload a port using https for example would\n\n```\nNative\nhttp.ListenAndServeTLS(\":8081\", \"cert.crt\", \"yourkey.key\", nil)\n\nUsing Mux\nconfServerHttps.ListenAndServeTLS(server.crt, yourke.Key)\n\n```\n\n# Using OpenSSL\n\nYou can generate the files with the openssl native linux command.\n\nWe will generate to authenticate in some server in the internet like rapidssl, gogetssl and thousands of others spread in the web, to simulate the production environment.\n\nWe will not use startssl for example that is free for 1 year, it is no longer recognized and our https on our server golang will go from error.\n\nThe -nodes option is not the English word \"nodes\", but it is \"in DES\".\n\nIt means that OpenSSL will not encrypt your private key.\n\nThis will prevent from initializing the server it prompts for password.\n\n\n```\nopenssl req -nodes -newkey rsa:2048 -keyout yourkey.key -out serve.csr\n\n```\n\nNow, is to send your csr to the server that will authenticate your key and issue your certificate for use of https, it will resend to you the files and what we will use on our golang server is .crt (Alternate synonymous most common Among * nix systems .pem (pubkey)).\n\n\nLook at the definition of the files:\n\n-  .crt — Alternate synonymous most common among *nix systems .pem (pubkey).\n-  .csr — Certficate Signing Requests (synonymous most common among *nix systems).\n-  .cer — Microsoft alternate form of .crt, you can use MS to convert .crt to .cer (DER encoded .cer, or base64[PEM] encoded .cer). \n-  .pem = The PEM extension is used for different types of X.509v3 files which contain ASCII (Base64) armored data prefixed with a «—– BEGIN …» line. These files may also bear the cer or the crt extension.\n- .der — The DER extension is used for binary DER encoded certificates.\n\n\n# Generating the Certficate Signing Request\n\nThere is another possibility that is to generate your own key signal.\nYou can also auto-sign your keys for local testing.\n\nI do not recommend you want to test and simulate a production-like environment, but it's good to learn and test.\n\nGeneration of self-signed(x509) / public key (.pem|.crt) based on the private (.key)\n\n```\nopenssl req -new -sha256 -key server.key -out server.csr\nopenssl x509 -req -sha256 -in server.csr -signkey server.key -out server.crt -days 3650\n\n```\n\n# Methods of our server\n\nBody of main type struct\n\n```go\n\n// Structure of our server configurations\ntype Configs struct {\n\tDomain     string `json:\"domain\"`\n\tProcess    string `json:\"process\"`\n\tPing       string `json:\"ping\"`\n\tServerPort string `json:\"serverport\"`\n\tHost       string `json:\"host\"`\n\tSchema     string `json:\"shcema\"`\n\tServerHost string `json:\"serverhost\"`\n\tUploadSize int64  `json:\"uploadsize\"`\n\tPathLocal  string `json:\"pathlocal\"`\n}\n\n```\n\nBody of main variables\n\n```go\n// Our global variables\nvar (\n\terr           error\n\treturns       string\n\tconfServer    *http.Server\n\tAUTHORIZATION = `bc8c154ebabc6f3da724e9x5fef79238`\n\tobjason       Configs\n)\n\n```\n\nBody of main function ConfigJson\n\n```go\n\n// This method ConfigJson sets up our\n// server variables from our struct\nfunc ConfigJson() string {\n\n\t// Defining the values of our config\n\tdata := \u0026Configs{Domain: \"localhost\", Process: \"2\", Ping: \"ok\", ServerPort: \"9001\", Host: \"\", Schema: \"http\", ServerHost: \"localhost\", UploadSize: 100, PathLocal: \"uploads\"}\n\n\t// Converting our struct into json format\n\tcjson, err := json.Marshal(data)\n\tif err != nil {\n\t\t// handle err\n\t}\n\n\treturn string(cjson)\n}\n\n```\n\nBody of main function UploadFileEasy\n\n```go\n\n\n// Method UploadFileEasy responsible for simulating our types of uploads,\n// types are: multipart / form-data using form or option -F | --form\n// of curl, application / octet-stream using --data-binary\nfunc UploadFileEasy(w http.ResponseWriter, r *http.Request) {\n\n\tnameFileUp := r.Header.Get(\"Name-File\")\n\n\t// This header was defined by our restful\n\t// server so we can understand and know\n\t// that the submitted type is a binary upload\n\n\tif nameFileUp != \"\" {\n\n\t\tuploadBinary(w, r)\n\n\t} else {\n\n\t\tuploadFormFile(w, r)\n\n\t}\n}\n\n```\n\nBody of main function uploadBinary\n\n```go\n\n// This method uploadBinary only receives files coming in binary format,\n// it will copy to disk what is coming via http\nfunc uploadBinary(w http.ResponseWriter, r *http.Request) {\n\n\tcfg := conf.Config()\n\n\tnameFileUp := r.Header.Get(\"Name-File\")\n\n\t// Upload octet-stream\n\tif nameFileUp != \"\" {\n\n\t\t// Creating the structure if it does not exist\n\t\tpathUpKeyUser := cfg.PathLocal + \"/\" + acessekey\n\t\texistPath, _ := os.Stat(pathUpKeyUser)\n\t\tif existPath == nil {\n\t\t\t// create path\n\t\t\tos.MkdirAll(pathUpKeyUser, 0777)\n\t\t}\n\n\t\t// Setting the path\n\t\tpathUpKeyUserFull := pathUpKeyUser + \"/\" + nameFileUp\n\n\t\t// In amazon does not receive multipart / form-data only application\n\t\t// / octet-stream ie --data-binary or instead of --form nameupload = @,\n\t\t// then we implement the 2 forms for our upload test\n\t\tff, _ := os.OpenFile(pathUpKeyUserFull, os.O_WRONLY|os.O_CREATE, 0777)\n\t\tdefer ff.Close()\n\n\t\t// Copying the contents of http body to our file\n\t\tsizef, _ := io.Copy(ff, r.Body)\n\n\t\t// Writing in our response\n\t\tw.Write([]byte(fmt.Sprintf(\"%d bytes are recieved.\\n\", sizef)))\n\n\t\tcolor.Red(\"File name: %s\\n\", nameFileUp)\n\t\tcolor.Yellow(\"copied: %v bytes\\n\", sizef)\n\t\tcolor.Yellow(\"copied: %v Kb\\n\", sizef/1024)\n\t\tcolor.Yellow(\"copied: %v Mb\\n\", sizef/1048576)\n\n\t\tmsgjson := conf.JsonMsg(200, \"ok upload size: \"+fmt.Sprintf(\"%d bytes are recieved.\\n\", sizef)+\" name file: \"+nameFileUp)\n\t\tfmt.Fprintln(w, msgjson)\n\n\t}\n}\n\n```\n\nBody of main function uploadFormFile\n\n```go\n\n// This method uploadFormFile only receives files coming in\n// the multipart / form-data format, ie comes from a form\n// sent by our client\nfunc uploadFormFile(w http.ResponseWriter, r *http.Request) {\n\n\tcfg := conf.Config()\n\n\t// Validating the upload FormFile\n\terrup := r.ParseMultipartForm(32 \u003c\u003c 20)\n\tif errup != nil {\n\n\t\tlog.Printf(\"Error: Content-type or submitted format is incorrect to upload  %s\\n\", errup)\n\t\tmsgjson := conf.JsonMsg(500, errup.Error())\n\t\tfmt.Fprintln(w, msgjson)\n\n\t\treturn\n\t}\n\n\t// Upload multipart/form-data\n\tsizeMaxUpload := r.ContentLength / 1048576 ///Mb\n\n\tif sizeMaxUpload \u003e cfg.UploadSize {\n\n\t\tfmt.Println(\"The maximum upload size: \", cfg.UploadSize, \"Mb is large: \", sizeMaxUpload, \"Mb\", \" in bytes: \", r.ContentLength)\n\n\t\tmsgjson := conf.JsonMsg(500, \"Unsupported file size max:\"+fmt.Sprintf(\"%v\", cfg.UploadSize)+\"Mb\")\n\t\tfmt.Fprintln(w, msgjson)\n\n\t} else {\n\n\t\t// Looking for the file in the FormFile method\n\t\tfile, handler, errf := r.FormFile(\"fileupload\")\n\n\t\tif errf != nil {\n\n\t\t\tlog.Println(errf.Error())\n\t\t\t//http.Error(w, errf.Error(), http.StatusBadRequest)\n\n\t\t\tmsgjson := conf.JsonMsg(500, errf.Error())\n\t\t\tfmt.Fprintln(w, msgjson)\n\t\t\treturn\n\t\t}\n\t\tdefer file.Close()\n\n\t\tif errf != nil {\n\t\t\tcolor.Red(\"Error big file, try again!\")\n\t\t\thttp.Error(w, \"Error parsing uploaded file: \"+errf.Error(), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tdefer file.Close()\n\n\t\t///create dir to key\n\t\tpathUpKeyUser := cfg.PathLocal + \"/\" + acessekey\n\n\t\texistPath, _ := os.Stat(pathUpKeyUser)\n\n\t\tif existPath == nil {\n\n\t\t\t// create path\n\t\t\tos.MkdirAll(pathUpKeyUser, 0777)\n\t\t}\n\n\t\tpathUserAcess := cfg.PathLocal + \"/\" + acessekey + \"/\" + handler.Filename\n\n\t\t// copy file and write\n\t\tf, _ := os.OpenFile(pathUserAcess, os.O_WRONLY|os.O_CREATE, 0777)\n\t\tdefer f.Close()\n\n\t\t// Copying the FormFile file to our local disk file\n\t\tsizef, _ := io.Copy(f, file)\n\n\t\t//To display results on server\n\t\tname := strings.Split(handler.Filename, \".\")\n\t\tcolor.Red(\"File name: %s\\n\", name[0])\n\t\tcolor.Yellow(\"extension: %s\\n\", name[1])\n\n\t\tcolor.Yellow(\"size file: %v\\n\", sizeMaxUpload)\n\t\tcolor.Yellow(\"allowed: %v\\n\", cfg.UploadSize)\n\n\t\tcolor.Yellow(\"copied: %v bytes\\n\", sizef)\n\t\tcolor.Yellow(\"copied: %v Kb\\n\", sizef/1024)\n\t\tcolor.Yellow(\"copied: %v Mb\\n\", sizef/1048576)\n\n\t\tmsgjson := conf.JsonMsg(200, \"ok upload size: \"+fmt.Sprintf(\"%d bytes are recieved.\\n\", sizef)+\" name file: \"+handler.Filename)\n\t\tfmt.Fprintln(w, msgjson)\n\t}\n\n}\n\n```\n\nBody of main function uploadFormFileMulti\n\n```go\n\n// This method is responsible for receiving multiple\n// files from uploading and writing the various files to disk.\nfunc uploadFormFileMulti(w http.ResponseWriter, r *http.Request, files []*multipart.FileHeader) {\n\n\tcfg := conf.Config()\n\n\tfmt.Println(\"size array: \", len(files))\n\n\t///create dir to key\n\tpathUpKeyUser := cfg.PathLocal + \"/\" + acessekey\n\n\t// Checking if the folder exists,\n\t// otherwise create the folder where\n\t// the files will be uploaded\n\texistPath, _ := os.Stat(pathUpKeyUser)\n\tif existPath == nil {\n\t\t// create path\n\t\tos.MkdirAll(pathUpKeyUser, 0777)\n\t}\n\n\tvar uploadSize int64\n\tnameFileString := \"\"\n\n\t// Reading multipart.File Header to loop\n\t// around the vector, and grab file by file and write to disk\n\tfor i, _ := range files {\n\n\t\tfile, err := files[i].Open()\n\t\tdefer file.Close()\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tfmt.Println(\"multi name: \", files[i].Filename)\n\t\tpathUserAcess := cfg.PathLocal + \"/\" + acessekey + \"/\" + files[i].Filename\n\n\t\t// copy file and write\n\t\tf, _ := os.Create(pathUserAcess)\n\t\tdefer f.Close()\n\n\t\t//copy the uploaded file to the destination file\n\t\tif sizef, err := io.Copy(f, file); err != nil {\n\n\t\t\tmsgerr := fmt.Sprintf(\"Copy MultiForm: %s\", err.Error()) + \" \" + fmt.Sprintf(\"%s\", http.StatusInternalServerError)\n\t\t\tmsgjson := conf.JsonMsg(500, msgerr)\n\t\t\tfmt.Fprintln(w, msgjson)\n\t\t\treturn\n\n\t\t} else {\n\n\t\t\tuploadSize += sizef\n\t\t\tnameFileString = nameFileString + \"; \" + files[i].Filename\n\t\t}\n\t}\n\n\t// Capturing sending of the request from the\n\t// sending example curl -F or --form,\n\t// curl -F \"email=jeff@yes.com\" -F \"password = 3939x9393\"\n\tcolor.Yellow(\"Get Form Data\\n\")\n\tfmt.Println(\"email: \", r.PostFormValue(\"email\"))\n\tfmt.Println(\"password: \", r.PostFormValue(\"password\"))\n\n\t//To display results upload\n\tcolor.Red(\"File name: %s\\n\", nameFileString)\n\tcolor.Yellow(\"size file: %v\\n\", uploadSize)\n\tcolor.Yellow(\"allowed: %v\\n\", cfg.UploadSize)\n\n\tmsgjson := conf.JsonMsg(200, \"ok upload size: \"+fmt.Sprintf(\"%d bytes are recieved.\\n\", uploadSize)+\" name file: \"+nameFileString)\n\tfmt.Fprintln(w, msgjson)\n}\n\n```\n\nWe created two routes one for homologation and one for production\n\n```go\n///create route\nrouter := mux.NewRouter().StrictSlash(true)\n\n// Opening an escape port for Homologation\nrTest := mux.NewRouter().StrictSlash(true)\n\n```\n\nBelow we define the individual config servers for when https config is different\n\n```go\n\n// Now it is possible to get on port 443 using https, \n// we did a check when it is https, the system \n// parameterizes config as needed\nif cfg.Schema == \"https\" {\n\n\t// .crt — Alternate synonymous most common among *nix systems .pem (pubkey).\n\t// .csr — Certficate Signing Requests (synonymous most common among *nix systems).\n\t// .cer — Microsoft alternate form of .crt, you can use MS to convert .crt to .cer (DER encoded .cer, or base64[PEM] encoded .cer).\n\t// .pem = The PEM extension is used for different types of X.509v3 files which contain ASCII (Base64) armored data prefixed with a «—– BEGIN …» line. These files may also bear the cer or the crt extension.\n\t// .der — The DER extension is used for binary DER encoded certificates.\n\t//\n\t// Setting our tls to accept\n\t// our .key and .crt keys.\n\tcfgs := \u0026tls.Config{\n\n\t\tMinVersion:               tls.VersionTLS12,\n\t\tCurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},\n\t\tPreferServerCipherSuites: true,\n\t\tCipherSuites: []uint16{\n\t\t\ttls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\n\t\t\ttls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,\n\t\t\ttls.TLS_RSA_WITH_AES_256_GCM_SHA384,\n\t\t\ttls.TLS_RSA_WITH_AES_256_CBC_SHA,\n\t\t},\n\t}\n\n\t// Config to upload our server\n\tconfServerHttps = \u0026http.Server{\n\n\t\tHandler:      router,\n\t\tAddr:         cfg.Host + \":\" + cfg.ServerPort,\n\t\tTLSConfig:    cfgs,\n\t\tTLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),\n\n\t\t// Good idea, good live!!!\n\t\t//WriteTimeout: 10 * time.Second,\n\t\t//ReadTimeout:  10 * time.Second,\n\t}\n\n} else {\n\n\t// Config to upload our server\n\tconfServerHttp = \u0026http.Server{\n\n\t\tHandler: router,\n\t\tAddr:    cfg.Host + \":\" + cfg.ServerPort,\n\n\t\t// Good idea, good live!!!\n\t\t//WriteTimeout: 10 * time.Second,\n\t\t//ReadTimeout:  10 * time.Second,\n\t}\n}\n\n// Config to upload our server\nconfServerHttpTest = \u0026http.Server{\n\n\tHandler: rTest,\n\tAddr:    cfg.Host + \":4001\",\n\n\t// Good idea, good live!!!\n\t//WriteTimeout: 10 * time.Second,\n\t//ReadTimeout:  10 * time.Second,\n}\n\n// Defining whether it is https or http,\n// if it is http leave the calls\n// without access keys\nif cfg.Schema == \"https\" {\n\n\tgo func() {\n\n\t\tlog.Fatal(confServerHttps.ListenAndServeTLS(cfg.Pem, cfg.Key))\n\n\t}()\n\n\tlog.Fatal(confServerHttpTest.ListenAndServe())\n\n} else {\n\n\tgo func() { log.Fatal(confServerHttp.ListenAndServe()) }()\n\n\tlog.Fatal(confServerHttpTest.ListenAndServe())\n}\n\n```\n\n## Example of curl client Sending file in binary format\n\n```\ncurl -i --request POST http://localhost:9001/postest \\\n-u \"API_KEY:383883jef903xxxx838xxxx\" \\\n-H \"Accept: binary/octet-stream\" \\\n-H \"Content-Type: binary/octet-stream\" \\\n-H \"Name-File: file1.jpg\" \\\n--data-binary \"@file1.jpg\"\n\n```\n## Example of curl client Sending file on multipart/form-data\n\n```\ncurl -i -X POST http://localhost:9001/postest \\\n-u \"API_KEY:383883jef903xxxx838xxxx\" \\\n--form \"fileupload=@files/file1.jpg\" \n\n```\n\n## Example using Api Gateway Aws  / Limit 10 MB per request\n\n```\ncurl -i --request POST https://xxxxxx.execute-api.us-xxx-x.amazonaws.com/goapigateway \\\n-u \"API_KEY:xxxxxx38383xxxx\" \\\n-H \"Accept: binary/octet-stream\" \\\n-H \"Content-Type: binary/octet-stream\" \\\n-H \"Name-File: file1.jpg\" \\\n--data-binary \"@files/file1.jpg\"\n\n```\n\n## Example Using json to tesar our post and get\n\n```\ncurl -i -X POST localhost:9001/postest \\\n-u API_KEY:383883jef903xxxx838xxxx \\\n-H \"Content-Type: application/json\" \\\n-H \"Authorization: jeff b7d03a6947b217efb6f3ec3bd3504582\" \\\n-d '{\"email\":\"jeffotoni@yes.com\",\"password\":\"3838373773\"}'\n\n```\n\n## Example Post text using Api Gateway Aws  / Limit 10 MB per request\n\n```\ncurl -i -X POST https://xxxxxx.execute-api.us-xxx-x.amazonaws.com/goapigateway \\\n-u API_KEY:383883jef903xxxx838xxxx \\\n-H \"Content-Type: application/json\" \\\n-H \"Authorization: jeff b7d03a6947b217efb6f3ec3bd3504582\" \\\n-d '{\"email\":\"jeffotoni@yes.com\",\"password\":\"3838373773\"}'\n\n```\n\n## Example using form data passing fields through url\n\n\n```\ncurl -i -X POST localhost:9001/postest \\\n-u API_KEY:383883jef903xxxx838xxxx \\\n-H \"Authorization: jeff b7d03a6947b217efb6f3ec3bd3504582\" \\\n-d -d \"email=jefferson\u0026password=3838373773\" \n\n```\n\n## Example using form data passing fields through url of Api Gateway Aws / Limit 10 MB per request\n\nThe content-type is not defined in this submission, Amazon's Api Gateway will not allow\n\n```\ncurl -i -X POST https://xxxxxx.execute-api.us-xxx-x.amazonaws.com/goapigateway \\\n-u API_KEY:383883jef903xxxx838xxxx \\\n-H \"Authorization: jeff b7d03a6947b217efb6f3ec3bd3504582\" \\\n-d 'email=jeff@\u0026password=38xxx8w8e'\n\n```\n\n## In a single request we send form fields and an upload file\n\nThe Amazon Gateway Api unfortunately does not accept --form for only binary file uploads then it will \nnot work using the upload to Amazon.\n\n```\ncurl -i --request POST localhost:9001/postest \\\n-u \"API_KEY:383883jef903xxxx838xxxx\" \\\n--form 'email=jefferson\u0026password=3838373773' \\\n--form \"fileupload=@files/file1.jpg\"\n```\n\n## In a single request we send form fields and multiple files to upload\n\nUnfortunately Amazon does not support --form / or better multipart / form-data for sending files only --data-binary\n\n```\ncurl -i --request POST localhost:9001/postest \\\n-u \"API_KEY:383883jef903xxxx838xxxx\" \\\n--form 'email=jefferson\u0026password=3838373773' \\\n--form \"fileupload[]=@files/file1.jpg\" \\\n--form \"fileupload[]=@files/file2.pdf\"\n\n```\n\n## We are using --cacert to read our bundle key so you can allow access to our https\n\n```\ncurl --cacert budle.pem -i \\\n-X POST https://myapp/postest \\\n-u \"API_KEY:383883jef903xxxx838xxxx\" \\\n--form 'email=jefferson\u0026password=3838373773' \\\n--form \"fileupload[]=@bigfile1.jpg\"\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffotoni%2Fgoapigateway","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffotoni%2Fgoapigateway","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffotoni%2Fgoapigateway/lists"}