-
Notifications
You must be signed in to change notification settings - Fork 570
Add optional root argument to gopherjs serve. Fixes #384 #429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This looks really good, thanks for contributing! Two small wishes:
|
Thanks for working on resolving that issue! I have some questions about the code changes. |
@@ -555,7 +571,7 @@ func (fs serveCommandFileSystem) Open(name string) (http.File, error) { | |||
if isPkg || isMap || isIndex { | |||
// If we're going to be serving our special files, make sure there's a Go command in this folder. | |||
s := gbuild.NewSession(fs.options) | |||
pkg, err := gbuild.Import(path.Dir(name[1:]), 0, s.InstallSuffix(), fs.options.BuildTags) | |||
pkg, err := gbuild.Import(path.Dir(strings.Trim(name, "/")), 0, s.InstallSuffix(), fs.options.BuildTags) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the first character was unconditionally dropped with name[1:]
it was always a slash. With this change the first character is sometimes a slash, but not always. I was seeing it pass strings like ithub.com/jargv/...
into path.Dir, which fails, of course. strings.Trim
seemed like a good way to conditionally drop the first character if it's a '/'. I'm new(ish) to go so I'd love to learn if there's a more idiomatic approach. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this change the first character is sometimes a slash, but not always.
I see. I asked I'd like to understand exactly in what situations it'a slash, and in what situations it's not.
strings.Trim
seemed like a good way to conditionally drop the first character if it's a '/'. I'm new(ish) to go so I'd love to learn if there's a more idiomatic approach. :)
One immediate improvement suggestion would be to use strings.TrimLeft
rather than strings.Trim
, since you said you only want to drop the first character being /
, not the last character. strings.Trim
trims from both ends.
However, I understand what's happening better now, and I have a suggestion for how you can go back to just having an unconditional trim of first character (which should be simpler to reason about).
The signature of this method used to be Open(name string)
, and name[1:]
used to be done to drop the first "/" that's a part of each *http.Request.URL.Path
. Since you've re-arranged the code to be Open(requestName string)
, I think you can move the the [:1]
operation to happen earlier:
func (fs serveCommandFileSystem) Open(requestName string) (http.File, error) {
name := path.Join(fs.serveRoot, requestName[1:])
Then this line can become simply:
pkg, err := gbuild.Import(path.Dir(name), 0, s.InstallSuffix(), fs.options.BuildTags)
What do you think of that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree TrimLeft would be better, and the move you suggest would be better still! I'll make that change shortly.
How does this change affect the source maps that are served as well? |
@shurcooL Source maps seem to work as expected with this change. |
@@ -35,6 +35,8 @@ For example, navigating to `http://localhost:8080/example.com/user/project/` sho | |||
|
|||
Refreshing in the browser will rebuild the served files if needed. Compilation errors will be displayed in terminal, and in browser console. Additionally, it will serve $GOROOT and $GOPATH for sourcemaps. | |||
|
|||
If you include an argument, it will be the root from which everything is served. For example, if you run `gopherjs serve example.com/user` then the generated JavaScript will be served at `http://localhost:7979/project/project.js`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how the command gopherjs serve example.com/user
maps to something being served at /project/
.
I also feel like making it a positional argument is confusing. Other tools (build, install) take the package as an argument. I can accept serve
not accepting a package, but IMO it shouldn't interpret the argument in an entirely different way. Wouldn't it make more sense to make this an explicit flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about changing it to this:
"For example, if you run gopherjs serve github.com/user/project
then the generated JavaScript for the package github.com/user/project/mypkg
will be served at http://localhost:7979/mypkg/mypkg.js
."
I think the semantics are not too far off compared to other commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I don't understand what the argument does. I thought gopherjs serve foo
would serve the package in $PWD at /foo/
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, okay. I guess it's fine then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does behave like other commands which take a package. It just also handles the case where the argument is not a complete package path, in which case it serves all packages at that root.
@@ -35,6 +35,8 @@ For example, navigating to `http://localhost:8080/example.com/user/project/` sho | |||
|
|||
Refreshing in the browser will rebuild the served files if needed. Compilation errors will be displayed in terminal, and in browser console. Additionally, it will serve $GOROOT and $GOPATH for sourcemaps. | |||
|
|||
If you include an argument, it will be the root from which everything is served. For example, if you run gopherjs serve github.com/user/project then the generated JavaScript for the package github.com/user/project/mypkg will be served at http://localhost:7979/mypkg/mypkg.js. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last thing: Let's use :8080
here, since that is the default.
LGTM |
I can see some minor followup enhancements, but no blockers for this getting merged to resolve #384. LGTM. |
I found an issue with sourcemaps that needs to be resolved before this can be merged. The source maps work well enough to map errors to the right file/line. So for example instead of the error being reported at The problem occurs when I click on |
I added a fix but it has an assumption. When the requested file ends in ".go" I ignore the serveRoot. The assumption is that source maps will only map to |
GopherJS also accepts *.inc.js files as input. I don't know if these are presently supported for source maps. If it's easy to support such files as well, I would encourage doing so. If that's presently not supported, then at least it's not a regression not to support them here. |
@flimzy source maps don't appear to work for .inc.js files. |
What about trying both? First try the prefixed path, but if that file does not exist then try the non-prefixed path? I think this should be possible by adding to |
@neelance I actually tried that first. The trouble I ran into was how serveCommandFileSystem.Open determines when to compile or not. Specifically these variables never evaluated to true: isPkg := file == base+".js"
isMap := file == base+".js.map" because base is derived from the request path. Of course this could be changed to work in some other way, but it's not clear to me that that would be simpler. For example, how would you disambiguate a request to That said, I'm happy to make the change if that's determined to be the best way forward. |
Ok I changed it to serve files both inside and outside of the serveRoot. There's no longer special casing around @neelance is this what you meant? I tried adding to serveCommandFileSystem.dirs in order to get rid of the serveRoot variable, but the problem becomes mapping back to a valid package path. Right now we can assume that the request path (with the serve root prepended) is a valid package without having to look through GOPATH and GOROOT looking for a match. Anything else to make this good to merge? |
Fixes #384.