Skip to content
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

Server returns html document with [object Promise] #1

Open
Nikjee opened this issue May 3, 2024 · 2 comments
Open

Server returns html document with [object Promise] #1

Nikjee opened this issue May 3, 2024 · 2 comments

Comments

@Nikjee
Copy link

Nikjee commented May 3, 2024

So i was really curious with this go ssr approach and went to try it but there was several issues.

  1. I had problems running docker container, running on M1 MBP and this dockerfile worked for me
FROM node:18-alpine as frontend

RUN npm install -g [email protected]

WORKDIR /app
COPY client ./client/

WORKDIR /app/client
RUN pnpm install --frozen-lockfile && pnpm build


FROM --platform=linux/amd64 ubuntu:latest as backend

# RUN apt update

ARG GO_VERSION
ENV GO_VERSION=${GO_VERSION}

RUN dpkg --add-architecture amd64
RUN apt-get update && apt-get upgrade
RUN apt-get install -y wget git gcc libc-dev make build-essential g++-x86-64-linux-gnu libc6-dev-amd64-cross gcc-aarch64-linux-gnu binutils:amd64 libc6-amd64-cross libstdc++6-amd64-cross

RUN ln -s /usr/x86_64-linux-gnu/lib64/ /lib64

ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/lib64:/usr/x86_64-linux-gnu/lib"
# RUN apt install gcc libc-dev make build-base

RUN wget -P /tmp "https://dl.google.com/go/go1.22.2.linux-amd64.tar.gz"

RUN tar -C /usr/local -xzf "/tmp/go1.22.2.linux-amd64.tar.gz"
RUN rm "/tmp/go1.22.2.linux-amd64.tar.gz"

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"

WORKDIR /app

COPY --from=frontend /app/dist ./dist

COPY pkg/ ./pkg/
COPY go.mod go.sum Makefile main.go ./
RUN go mod download

RUN make build


FROM --platform=linux/amd64 ubuntu:latest as final

WORKDIR /app

COPY --from=backend /app/build/ /app/

EXPOSE 8080

CMD ["/app/server"]

And Makefile, not sure if it did anything but it is what it is

build:
	# build the backend
	env GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o $(BUILD_DIR)/$(APP_NAME) main.go

  1. As title says server returns a Promise in a string so for that i had to find a way to wait for it, on v8 repo in issues i found this posted
func resolvePromise(ctx *v8go.Context, val *v8go.Value, err error) (*v8go.Value, error) {
	if err != nil || !val.IsPromise() {
		return val, err
	}
	for {
		switch p, _ := val.AsPromise(); p.State() {
		case v8go.Fulfilled:
			return p.Result(), nil
		case v8go.Rejected:
			return nil, errors.New(p.Result().DetailString())
		case v8go.Pending:
			ctx.PerformMicrotaskCheckpoint() // run VM to make progress on the promise
			// go round the loop again...
		default:
			return nil, fmt.Errorf("illegal v8go.Promise state %d", p) // unreachable
		}
	}
}

And in a nutshell what we need to do is this

func (r *Renderer) Render(urlPath string) (string, error) {
	iso := r.pool.Get()
	defer r.pool.Put(iso)

	ctx := v8go.NewContext(iso.Isolate)
	defer ctx.Close()

	iso.RenderScript.Run(ctx)

	renderCmd := fmt.Sprintf(`ssrRender("%s")`, urlPath)
	val, err := ctx.RunScript(renderCmd, r.ssrScriptName)
	result, _ := resolvePromise(ctx, val, err)

	if err != nil {
		if jsErr, ok := err.(*v8go.JSError); ok {
			err = fmt.Errorf("%v", jsErr.StackTrace)
		}
		return "", nil
	}

	return result.String(), nil
}

Maybe for the future there should be a check if a value of a script is a Promise then we wait for it otherwise just return a string.

I'm not sure if you want to add this edits but for people who will come upon this might help

@jaybeecave
Copy link

Ty for posting this. :)

@revenkroz
Copy link
Owner

Thanks! I updated packages and added check for promise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants