Serving files with Echo - go

I'm trying to serve multiple files with Echo, but it doesn't work every time.
The api code looks like this:
package main
import (
"github.com/labstack/echo"
"net/http"
)
func main() {
e := echo.New();
e.GET("/", home);
e.File("/data1", "assets/data1.csv");
e.File("/data2", "assets/data2.csv");
e.Logger.Fatal(e.Start(":4243"));
}
func home(c echo.Context) error {
return c.String(http.StatusOK, "Are you lost?");
}
To be precise, it does work for the very first file fetching, but then keeps failing for any subsequent calls (be them file fetching or more "classic" calls). The error message is a tad different for each browser:
In Chrome:
SyntaxError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'Bearer {the_entire_content_of_the_first_fetched_file}' is not a valid HTTP header field value.
In Firefox:
SyntaxError: An invalid or illegal string was specified
In Edge, simply:
SyntaxError
Tried activating CORS, nothing changed.
Looks to work pretty well with Postman. Maybe it's a problem with how I do fetch my data in my application?
If you need perhaps a bit more information, this thread is directly related to my previous one (Vuejs with axios request in vuex store: can't make more than one request, why?), but I didn't want to mix them up, as I don't know yet if I'm mistaken in my Vue code or my Echo one...

If you would like to delivery files from certain directory. You can do following ways:
e.Use(middleware.Static("/path/to/directory"))
OR
fs := http.FileServer(http.Dir("/path/to/directory"))
e.GET("/assets/*", echo.WrapHandler(http.StripPrefix("/assets/", fs)))

Just Add default CORS Middleware, i just test and it's work fine even i using difference domain.
import this package from echo framework: "github.com/labstack/echo/middleware"
and Add this default CORS config befor your route:
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"*"},
AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE},
}))

Welp, seems it was my application's fault all along! My Echo api seems fine... for now!
If someone has the same problem, perhaps this Vuejs with axios request in vuex store: can't make more than one request, why? will help.

Related

Get raw parameters from react router

Is there any way to get the raw (without URL decoding) parameters from the react router V6.3 without making my own windows.location.href parser?
Example:
path: /companies/Samsung%2CInc,Lenovo%2CInc
const params = useParams();
const companies = params.companies?.split(',');
Expected:
[
'Samsung%2CInc',
'Lenovo%2CInc',
]
Getting:
[
'Samsung',
'Inc',
'Lenovo',
'Inc',
]
Any recommendations here?
PS. React Router does URL Decode, which is what I want to avoid. I found related issue on lib's issues board.
Apparently it is not possible at this moment. The URL decoding is coming from the matching part, which is a way deeper than useParams method.
I created a workaround gist that uses already parsed params and obtaining their RAW (URL encoded) version from the location.pathname
It works for my case, but I'm sure it could be optimized.

GoLang web service - How to translate errors declared in package

I'm implementing server using GIN Framework.
The Gin framework has a handler for each route.
Each function handler has it's own controller that returns some result (basically error)
package controller
var (
ErrTooManyAttempts = errors.New("too many attempts")
ErrNoPermission = errors.New("no permission")
ErrNotAvailable = errors.New("not available")
)
This errors are created for developers and logging, so we need to beautify and translate these before sending them to the client.
To be able to get translation we should know the key of the message.
But the problem is I need to bind these errors in some map[error]string (key) to get translation key by error.
It's quite complex because I have to bind all the errors with the corresponding keys.
To improve it, I'd like to use reflection:
Get all variables in the package
Walk through and find Err prefix
Generate translation key based on package name and error name, ex: controller-ErrTooManyAttempts
Merge translation file, so it should look like this:
`
{
"controller-ErrTooManyAttempts": "Too many attempts. Please try again later",
"controller-ErrNoPermission": "Permission to perform this action is denied",
"controller-ErrNotAvailable": "Service not available. Please try again later"
}
`
What is the correct way to translate errors from the package? Is it possible to provide me with some example?

Empty request body and missing headers with custom handler

I have an Azure Function which uses a custom handler written in Go. It was all working fine until Friday and now the requests appear to be turning up with empty request bodies and missing headers? Has anyone else experienced this?
The Go handler is really simple...
func main() {
httpInvokerPort, exists := os.LookupEnv("FUNCTIONS_HTTPWORKER_PORT")
if exists {
log.Printf("FUNCTIONS_HTTPWORKER_PORT: %s\n", httpInvokerPort)
}
mux := http.NewServeMux()
mux.HandleFunc("/sign", httpTriggerHandler)
log.Println("Go server Listening...on httpInvokerPort:", httpInvokerPort)
log.Fatal(http.ListenAndServe(":"+httpInvokerPort, mux))
}
And the handler function:
func httpTriggerHandler(w http.ResponseWriter, r *http.Request) {
spew.Dump(r)
// other app logic
}
Since late last week, the spew shows an empty request body (where there should be JSON), and a few missing headers. I've not changed anything in the code, and can't see any major changes to the Azure Functions service.
I've done some troubleshooting, including MITM'ing myself outbound to ensure that the request is leaving my machine well-formed and it all seems fine. I've also tried redeploying to other Azure regions.
This is now resolved: https://github.com/Azure/azure-functions-host/issues/6444. There was a bug in the Azure Functions Host which has been fixed.

static files not served correctly when using wildcard

Using GOA, I defined a service to serve static files using a wildcard (as described in the documentation):
var _ = Service("static", func() {
Files("/static/*filepath", "./static/")
})
But when I run the service, the endpoint always retrieves all the content it finds in the ./static/ directory, it seems it doesn't take into account the wildcard section at all.
For example, if I have ./static/uploads/file1.jpg and I request localhost/static/uploads/file1.jpg or localhost/static/anything , then the service retrieves the following:
<pre>
uploads/
</pre>
Digging into the code, I believe the problem is in the generated /gen/http/static/server/server.go file:
// Mount configures the mux to serve the static endpoints.
func Mount(mux goahttp.Muxer, h *Server) {
MountCORSHandler(mux, h.CORS)
MountStatic(mux, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/")
}))
}
// MountStatic configures the mux to serve GET request made to
// "/static/*filepath".
func MountStatic(mux goahttp.Muxer, h http.Handler) {
mux.Handle("GET", "/static/*filepath", handleStaticOrigin(h).ServeHTTP)
}
For what I see, the generated code is serving what we passed as base path no matter what, it doesn't take into account if we configured a wildcard at all (it only uses it to match the request, but not to customize the file that we'll serve).
I believe this was working ok in v2, I found this issue in the process of migrating to v3.
As I said, this seems like a bug in GOA, but maybe I'm missing something here. I created an issue in the repo to obtain more information (#2321)
As per the answer in the Github issue (#2321), it seems there was an error in the docs, and we should use curly braces in the pattern:
Thank you for the report, there is a typo in the docs, the path in the design needs to be /static/{*filepath} instead (with curly braces surrounding the wildcard).

Django Channels - Handshaking & Connect, but websocket.connect function is not executed

I'm working on a django project with channels involved in different apps. The first app (receiving data from a sensor) has it's own consumer and routing, as well as the second one (updates a list of logged in users).
Within the first app everything works fine.
In the second app the handshake is completed and the connection is established, but the function, that is linked to websocket.receive is not executed.
from channels.routing import route, route_class
from channels.staticfiles import StaticFilesConsumer
from users.consumer import ws_connect, ws_disconnect
channel_routing = [
route('websocket.connect', ws_connect, path=r'^/users/lobby/'),
...
]
and the ws_connect
import json
from channels import Group
from channels.handler import AsgiHandler
from channels.auth import channel_session_user,
channel_session_user_from_http, channel_session
#channel_session_user_from_http
def ws_connect(message):
print('test')
The print('test') of ws_connect is never executed. Additionally it even doesn't matter what url ending I'm using in javascript.
var ws = new WebSocket('ws://127.0.0.1:8000/users/lobby/');
ws.onopen = function() {
console.log('connect');
ws.send('connect');
}
The ws of the javascript will connect with .../users/lobby/ or .../lobby/ of .../users/.
Thanks for any hints on this!
Since i apparently need 50 reputation to make a comment i'm just gonna make an answer instead even tho i am not sure this is the solution for you.
I had the same exact problem when copying parts of the the github multichat project made by the guy whom made channels.
My issue was apparently that i hade miss spelled the routing with a slight misstake and therefor it didn't call the correct function i had setup for that routing.
So my advice is that you trippel check the routing everywhere to see if you've messed up. I personally only checked my APP routing when error checking but it was in my project folder i had messed upp my routing.
Another thing that might be cauzing this issue is that you only have a routing in your app, but not in the main folder. In that case you need to include the other app routing with the path you want for it just like a view:
from channels import include
channel_routing = [
include("crypto_chat.routing.websocket_routing", path=r"^/chat/stream/$"),
include("crypto_chat.routing.chat_routing"),
]
App routing:
from channels import route
from .consumers import ws_connect, ws_receive, ws_disconnect, user_offline, user_online, chat_send
websocket_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_receive),
route("websocket.disconnect", ws_disconnect),
]
chat_routing = [
route("chat.receive", chat_send, command="^send$"),
route("chat.receive", user_online, command="^online$"),
route("chat.receive",user_offline, command="^offline$"),
]
If that doesnt help then i suggest you head over to the github channel page for examples and compare the two. Keep in mind tho that the project is probably made from an erlier version of channels (and maybe django aswell).
https://github.com/andrewgodwin/channels-examples
Hope it helps and as i said i would have made a comment but i can't since of my rep apparently...

Resources