How to serve index.html on non root path using golang - go

I want to serve my angular app index.html under localhost:3000/mypath/ is there a way to accomplish that?
package main
import (
"net/http"
)
func main() {
// This works
http.Handle("/", http.FileServer(http.Dir("./my-project/dist/")))
// This doesn't work, you get 404 page not found
http.Handle("/mypath/", http.FileServer(http.Dir("./my-project/dist/")))
http.ListenAndServe(":3000", nil)
}

Remove the / handler, and change the /mypath/ handler into code below:
http.Handle("/mypath/", http.StripPrefix("/mypath/", http.FileServer(http.Dir("./my-project/dist/"))))
The http.StripPrefix() function is used to remove the prefix of requested path. On your current /mypath handler, every request will be prefixed with /mypath/. Take a look at example below.
/mypath/index.html
/mypath/some/folder/style.css
...
If the requested url path is not stripped, then (as per above example) it'll point into below respective locations, which is INVALID path and will result file not found error.
./my-project/dist/mypath/index.html
./my-project/dist/mypath/some/folder/style.css
...
By stripping the /mypath, it'll point into below locations, the correct one.
./my-project/dist/index.html
./my-project/dist/some/folder/style.css
...

Related

Golang kubernetes client - patching an existing resource with a label

I want to patch an existing secret resource within Kubernetes. The object is called centos-secretstorage within the default namespace. I want to add a simple label of test: empty. However, this fails when the secret object centos-secretstorage exists, but it doesn't have any existing labels. If I manually label the secret with something else beforehand via kubectl label centos-secretstorage hello=world, and rerun my golang code. It is able to add the test: empty label successfully.
However, I want to have this be able to add a label regardless if existing labels exist or not.
type secret struct {
namespace string
name string
}
func main() {
k8sClient := k8CientInit()
vaultSecret := secret{
namespace: "default",
name: "centos-secretstorage",
}
vaultSecret.patchSecret(k8sClient)
}
type patchStringValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
func (p *secret) patchSecret(k8sClient *kubernetes.Clientset) {
emptyPayload := []patchStringValue{{
Op: "add",
Path: "/metadata/labels/test",
Value: "empty",
}}
emptyPayloadBytes, _ := json.Marshal(emptyPayload)
fmt.Println(string(emptyPayloadBytes))
emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.JSONPatchType, emptyPayloadBytes)
if emptyerr != nil {
log.Fatal(emptyerr.Error())
}
fmt.Println(emptyres.Labels)
}
Error: the server rejected our request due to an error in our request
The problem is that the add operation in the JSON patch strategy requires the path to point to an existing map, while the object you are patching does not have this map at all. This is why when any label exists, the patch succeeds. We can work around this by using a different patch strategy. I think the merge strategy should work well.
I was able to reproduce this (on a namespace, but the object doesn't matter) using kubectl (which is generally useful when debugging the Kubernetes API):
kubectl patch ns a --type='json' -p='[{"op": "merge", "path": "/metadata/labels/test", "value":"empty"}]' -> fails
kubectl patch ns a --type='merge' -p='{"metadata": {"labels": {"test": "empty"}}}' -> succeeds
Using Golang client-go it would look something like this (didn't actually compile / run this):
payload := `{"metadata": {"labels": {"test": "empty"}}}`
emptyres, emptyerr := k8sClient.CoreV1().Secrets(p.namespace).Patch(p.name, types.MergePatchType, []byte(payload))
You can make the creation of the payload JSON nicer using structs, as you did with patchStringValue.
More info on patch strategies can be found here:
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
https://erosb.github.io/post/json-patch-vs-merge-patch/

type clientv3.Config has no field or method Username

the code is:
import (
"context"
"crypto/tls"
"time"
"go.etcd.io/etcd/clientv3"
)
func main(){
...
config := clientv3.Config{}
config.Username = u.username
...
}
go.mod file
module github.com/xxx
go 1.17
require (
github.com/coreos/etcd v2.3.8+incompatible // indirect
go.etcd.io/etcd v2.3.8+incompatible // indirect
)
It fails with this message:
config.Username undefined (type clientv3.Config has no field or method Username)
Is there a way to resolve this problem?what's the difference between github.com/coreos/etcd/clientv3 and go.etcd.io/etcd?
go.etcd.io/etcd/clientv3 and go.etcd.io/etcd/client/v3 are, somewhat confusingly, distinct packages that both use the package name clientv3.
The client/v3.Config type has the Username field you expect, so perhaps you can update your code to import that package instead of the other one?
import (
…
"go.etcd.io/etcd/client/v3"
)
(https://play.golang.org/p/2SK2FUNxWs9)
github.com/coreos/etcd/clientv3 was an older name for the package from the github.com/coreos/etcd repo before they adopted Go modules. When they moved to modules, they changed the canonical import path to go.etcd.io/etcd/client/v3, but (through some quirks of the Go module system) a hybrid of the old and new paths can still be resolved, using the code from the old path but served from the new URL. You probably want to use only the new canonical path.

How do I include my own tracer file into eth/tracers for go-eth?

I've modified the call_tracer.js file (https://github.com/ethereum/go-ethereum/tree/master/eth/tracers/internal/tracers)for my own requirements, however I'm unsure as to how include it along with the other tracers.
Right now, I'm feeding my tracer JS code as an input for debug_traceCall as below:
TxObj_TraceConfig := DebugTraceCallTraceConfig{
Tracer: "{My TRACER JS CODE}",
}
var raw json.RawMessage
err := rpcClient.CallContext(context.Background(), &raw, "debug_traceCall", TxObj, "latest", TxObj_TraceConfig)
var res DebugTraceCallTraceResponse
json.Unmarshal(raw, &res)
I'd like to instead specify the Tracer file as you do usually i.e. Tracer :"callTracer" or in my case Tracer : "customTracer".
I'm assuming that I will need to include my Tracer in assets.go ?
It should be sufficient to place the *.js file into the go-ethereum/eth/tracers/js/internal/tracers/tracers/ directory.
The code in tracers.go should include all JS files into the geth binary and make it available as the filename without the extension.

Golang invalid import path when importing from "main" folder

Been trying for the last few days to get rid of "invalid import path:"Atom First project/main/Extension" (build)" error when installing my main.go file but i haven't been able to find the reason behind the error.
OS - Windows 10
IDE - Atom
GOBIN - E:\Github Repository\Programming\Golang\bin
GOPATH - E:\Github Repository\Programming\Golang
File DIR- E:\Github Repository\Programming\Golang\src\Atom First project\main\main.go
E:\Github Repository\Programming\Golang\src\Atom First project\main\Extension/foo.go
main.go
package main
import (
"Atom First project/main/Extension"
)
func main() {
Extension.Extend()
}
foo.go
package Extension
import (
"fmt"
)
func Extend(){
fmt.Println("Hello from Extend func")
}
It's simple: import paths cannot contain spaces. Spec: Import declarations:
Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to Unicode's L, M, N, P, and S general categories (the Graphic characters without spaces) and may also exclude the characters !"#$%&'()*,:;<=>?[]^`{|} and the Unicode replacement character U+FFFD.
Simply rename your Atom First project folder to e.g. atom-first-project, and change the import declaration.
import (
"atom-first-project/main/Extension"
)
Also note that the package name (which is usually the folder name but not necessarily) must be a valid Go identifier. Spec: Package clause:
A package clause begins each source file and defines the package to which the file belongs.
PackageClause = "package" PackageName .
PackageName = identifier .

Django-Rest-Framework: router not working

I have this base urls file:
url(r'^locations/', include('locations.urls')),
in locations.urls.py app i have following url references:
url(r'^/?$', LocationList.as_view()),
url(r'^(?P<pk>[a-zA-Z0-9\-\$]+)/?$', LocationDetail.as_view()),
url(r'services/?$', LocationServiceseList.as_view()),
url(r'services/(?P<service_id>[a-zA-Z0-9\-\$]+)/?$', LocationServicesDetail.as_view()),
For above url referce i want to user routers of Django-Rest-framework
for locations/services/ i created GenericViewSet from DRF and i tried router successfully made following changes in locations.urls:
router = routers.SimpleRouter()
router.register(r'services', LocationServiceSet)
url(r'^/?$', LocationList.as_view()),
url(r'^(?P<vehicle_id>[a-zA-Z0-9\-\$]+)/?$', LocationDetail.as_view()),
url(r'^', include(router.urls)),
Now i want to create router for /locations/ endpoinsts and made following changes
router = routers.SimpleRouter()
router.register(r'services', LocationServiceSet)
router.register(r'', LocationSet)
url(r'^', include(router.urls)),
Getting 404 for /locations/ with stacktrace shows although /locations/services/ work fine:
^locations/ ^ ^services/$ [name='locationsservice-list']
^locations/ ^ ^services/(?P<pk>[^/.]+)/$ [name='locationsservice-detail']
^locations/ ^ ^/$ [name='locations-list']
^locations/ ^ ^/(?P<pk>[^/.]+)/$ [name='locations-detail']
This is happening because of an empty string prefix argument to router.register() function for LocationSet.
When you used an empty string '' as prefix for registering the router, it generated the following urls. (Notice the double slash in urls)
locations//$ # double slash in urls
locations//(?P<pk>[^/.]+)/$ # double slash in urls
To solve this, you need to define and register this router in base urls file instead of locations/urls.py with prefix value as locations.
# base urls.py
router = routers.SimpleRouter()
router.register(r'locations', LocationSet)
...
url(r'^locations/', include('locations.urls')), # include app urls
url(r'^', include(router.urls)), # include router urls
Another solution is to use a non-empty string as prefix while registering the router for LocationSet in locations/urls.py.

Resources