Loading a needed file, relative vs absolute paths - file

We have a program people can compile on their machines. It has an HTTP interface but can also be invoked by command line.
In order to provide some nice-looking error pages for HTTP clients, we want to provide error pages. We are using a very simple solution with go's html/template package.
So in order for the program to find the templates, we currently do:
func init() {
prefStr := "path/to/http/tmpl"
pathPrefix,err := filepath.Abs(prefStr)
if err != nil {
log.Warn("Template path %s is not available!", prefStr)
}
pathPrefix + "/err.html"
}
Now when debugging the app, this usually works well - we are in the package's root directory, so filepath.Abs() resolves correctly, like so:
$GOPATH/github.com/user/repo/path/to/http/tmpl (expanding $GOPATH correctly)
But when we invoke the app via executable from the command line, this doesn't work. The command line could of course be invoked from anywhere on the filesystem, for convenience for example to provide a file in the current directory as a parameter.
In short, running /some/other/path/on/fs/our-executable filename.txt results in the init() function above breaking due to wrong concatenation of the directory: it takes /some/other/path/on/fs/ to create the absolute path, which is wrong. Thus it crashes with
panic: open /some/other/path/on/fs/path/to/http/tmpl/err.html: no such file or directory
I've searched and so far only found this:
How can I open files using relative paths in Go?
But this exactly doesn't apply for us.
Another solution proposes to bundle compiled go resources, but this seems rather odd as the error pages are html text.
We've also tried
https://stackoverflow.com/a/31464648/169252
but it has the same effect.
How can we make sure that the paths are always resolved correctly? This seems rather something which shouldn't be too difficult to be done, but we haven't managed so far.
EDIT: This is not an exact duplicate of the question How can I open files using relative paths in Go?. As already mentioned in my question text, I already had looked it up myself. It suggests to use filepath.Abs(). But as laid out in my question, for us this doesn't work, as if our executable is called from different places, filepath.Abs() doesn't return the same value, and thus doesn't work for us.

I think your challenge here is that people can install the program anywhere on the disk and the program will have to be smart enough to know where it is later on.
One of the common approach that I have seen is that people typically use environment variables to anchor them to the application's installation path. I believe you may have seen environment variables with naming pattern of *_HOME like JAVA_HOME, MAVEN_HOME and their values are always filepath to the installation place.
I guess you can do the same here. Force your users to have MYAPP_HOME variable define and at the start of the application make sure that it is set or else throw an error saying MYAPP_HOME is not set.
Then all you need to do would be a simple lookup of the value for MYAPP_HOME + /http/tmpl to source for the template html files.
Example:
package main
import "os"
func main() {
// Assuming MYAPP_HOME has been verified that it is set
// Then:
tmlPath := os.Getenv("MYAPP_HOME") + "/http/tmpl/"
errTml := tmlPath + "err.html"
}

If you're not keen on using the current working directory, or passing the directory in, you can find the absolute executable path by calling os.Executable from the os package.
appPath, err := os.Executable()
The os package will generally contain os specific stuff like how to get the current working directory. It's worth looking through the pkg docs and list of packages at golang.org if your'e ever stuck, as they are pretty good typically you'll find an answer there.
https://golang.org/pkg/os
Another approach you can take here if users install with go get is to rely on the fact that your templates will be installed with the pkg under GOPATH, so you can always find them at $GOPATH/src/your/project/path/templates (or ~/go the default gopath now that it is not strictly required).
The safest way is probably to bundle them with the binary in a virtual file system as this means you depend on nothing external and don't care where your app is hosted or even if it has access to files at all.

I recommend using a relative path in this case.
According to your description, it seems like you are developing a web application. While it works fine on individual developer's machine, you need to be mindful that your application can be deployed under any directory on your production server. You cannot determine where you app is going to be deployed, but you can always determine where static files are relative to the root directory of your app.
When you invoke your app in the command line, you should have all the required static files copied to the same relative path exactly the same with your development environment. My typical structure is:
project/
|- config.json
|- main.go
|- package1/
|- package2/
|- static/
|- templates/
| |- index.html
| |- base.html
|- css/
|- javascript/
|- image/
When you are ready to run your application from command line, be sure to copy your config.json and the static/ directory to the same level as your executable binary. Then all you need to do is to use relative paths in your code without any nightmares.

For the records: as we just have two templates, we resorted to store them as strings in a go file so that they get compiled. Our html templates are very simple, so this is a reasonable way to do it.

Related

React suddenly responding with index.html instead of javascript imports

Recently I've been unable to load javascript scripts to my webworkers in react for some reason. It always responds with index.html.
My config is simply a standard create-react-app app. The screenshots are from my actual project but I have confirmed that the problem persists if I create a new project and try to initialize a minimal example.
Each ffmpeg.* file is affected. This is also not specific to ffmpeg since another library had the same issue - thankfully the initialization of that library is simpler so I was able to simply put that libraries worker-file in the public folder - and that worked.
It might be a stupid question but I'm really at my wits end here and I can't figure out how to investigate further.
Thank you <3
EDIT:
It works if I put all the files it is trying to hit in the public folder - so it has to be some kind of context issue(??) This seems like a really stupid way to go about it. It's not in a worker at the point of loading - it's the worker loader that fails to access the stuff it needs in the node_modules folder, (core script, worker script and wasm code). Whet?

Gatsby build path issues

Having issues running gatsby build with gatsby-starter-wordpress-advanced theme:
Error: ENOENT: no such file or directory, open 'C:\Users\Tobias\Desktop\Gatsby\gatsby-starter-wordpress-advanced\.template-cache\tmp-\.js'"
I figured this might be a problem with the path. The path should rather look like:
writing tmp-new-page/ template: open '.template-cache/tmp-new-page.js'
See repo: https://github.com/henrikwirth/gatsby-starter-wordpress-advanced/blob/master/create/utils.js
Line 53 you find the function createPageWithTemplate. I've tried console.log(page.uri) to see what's going on. It outputs the filename correctly. I've also tried with gatsby clean to clear the cache. It seems to be some kind of backslash issue where the path comes with a \ .js at the end instead of sample-page.js:
no such file or directory, open 'C:\Users\Tobias\Desktop\Gatsby\gatsby-starter-wordpress-advanced\.template-cache\sample-page\.js'
The issue have been resolved. The problem was related to update in WPGraphQL WordPress plugin. Had to update the paths, because the page.uri is different in the newer versions of WPGraphQL. Before it was just: some-page now it is /some-page/.
Secondly in the page template creation process the theme was using the uri, therefore, this messed up the paths for the template files. This has been switched to page.slug instead now and some extra checks, to make sure the frontPage is not ending up producing a wrong path.
The master branch of the starter theme have been updated.

Basic understanding - Location of public directory in React app

I'm building a React app with webpack. I was curious about where to put my "public" folder. I know in create-react-apps, the public folder is outside the "src" folder.
I'm not sure I'm clear on why you would want your public assets outside of your source folder. Is index.html not part of src? Is that not a crucial part of your code? Why would you put the public folder outside on it's own?
I'm trying to find good reading on this topic, but it seems folder structures are very subjective. If anyone could explain this, I would appreciate it. I want to firmly understand why the public folder is outside the src folder in create-react-app.
You posted this quite a number of months ago and I am surprised that there have been no responses as you raise an interesting point.
I believe the answer to be somewhat historic. In the past, the public folder was, indeed, public, meaning it contained a well-structured and hand-crafted index.html file and perhaps some other artifacts. These were intended to be consumed "as-is" while other parts of the application (i.e., JavaScript) remained in their own folder to be transpiled, merged, etc.
But that was then and this is now.
With the advent of modern packaging/bundling tools (webpack, brunch, parcel, and so on), such a distinction is no longer relevant nor does anyone really give it much thought.
With these bundling tools, everything is "source code" (as you pointed out) with the tools transforming index.html to correctly reference bundled CSS and JavaScript code.
So, while I cannot speak directly for the create-react-app team, I would submit that the public folder concept is largely an anachronism harkening back to the days where it really was public.
These days, everything ends up in a dist folder, which is then served to the end user. The machinery that creates this dist folder is largely ambivalent on how you structured the tool's input to arrive at the final distribution. Basically, the tools do not care about a public/src folder distinction, so why should you?
I hope that helps. I personally have index.html right alongside index.js in the src folder. The process is src -> bundler -> dist (just like good old C programming: src -> compiler -> exe).

Go Package Conflict

I am new to Go and AppEngine. I am trying to figure out how to create packages but I keep running into conflicts. My directory structure is below:
GOPATH
third-party-libs
app
app.yaml
controllers
default.go -- package controllers
models
models.go -- package models
templates
templates.go -- package templates
I am importing the templates package as follows import ("app/templates") inside default.go
When I do goapp serve I get this error:
Failed parsing input: app file templates.go conflicts with
same file imported from GOPATH
I have tried a bunch of things and nothing has worked so far. These are things I have tried:
Changed the templates directory to apptemplates and the corresponding file to apptemplates.go, changed package name to apptemplates. I imported it as app/apptemplates
I tried different combinations by changing the file name but not the package name, vice versa, etc. Either it does not find the file or has a conflict.
I am importing html/template in my templates.go file. So I commented out the entire file just keeping the package declaration but did not make the conflict go away
I thought may be another file is named templates.go but when I do this (at the GOPATH level) find . -name "*.go" | grep "templates.go" I only see the one file I have created.
I am confused as to how packages are created. I have changed the name to something generic so it does not look like a naming issue. Can someone please tell me how I can debug this error?
Thanks!
Rename the package to a non-conflicting name as in #1. Import the package using the path "apptemplates".
Packages inside of the application directory (the directory containing app.yaml) are imported with a path relative to the application directory. See Organizing Go Apps for the complete details.

How to use JST namespace in generator-backbone?

By default (in project's grunt file) the templates.js file located in .tmp directory (generator-backbone), so am I missing something or this feature just don't work out of the box and I need to put additional paths in require.config?
Obviously if I will not add anything the JST will not be defined, right?
Note that I initiated the projects with Handlebars as the templating framework.
Ah - sorry for trashing SO. Obviously I've messed up paths in my Grunt.js.
Only .tmp/scripts directory is mounted and I've added app to the path additionally, so the files was not served at all.

Resources