mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-09 17:12:14 +01:00
updating with current version of 6.1.0 branch
This commit is contained in:
5
Makefile
5
Makefile
@@ -5,7 +5,7 @@ DOCKER_PASSWORD=
|
||||
DOCKER_REGISTRY=thecodingmachine
|
||||
GOTENBERG_USER_GID=1001
|
||||
GOTENBERG_USER_UID=1001
|
||||
GOLANGCI_LINT_VERSION=1.19.1
|
||||
GOLANGCI_LINT_VERSION=1.20.1
|
||||
CODE_COVERAGE=0
|
||||
TINI_VERSION=0.18.0
|
||||
MAXIMUM_WAIT_TIMEOUT=30.0
|
||||
@@ -17,6 +17,7 @@ DEFAULT_LISTEN_PORT=3000
|
||||
DISABLE_GOOGLE_CHROME=0
|
||||
DISABLE_UNOCONV=0
|
||||
LOG_LEVEL=INFO
|
||||
ROOT_PATH=/
|
||||
DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE=1048576
|
||||
|
||||
# build the base Docker image.
|
||||
@@ -57,7 +58,7 @@ image:
|
||||
|
||||
# start the API using previously built Docker image.
|
||||
gotenberg:
|
||||
docker run -it --rm -e MAXIMUM_WAIT_TIMEOUT=$(MAXIMUM_WAIT_TIMEOUT) -e MAXIMUM_WAIT_DELAY=$(MAXIMUM_WAIT_DELAY) -e MAXIMUM_WEBHOOK_URL_TIMEOUT=$(MAXIMUM_WEBHOOK_URL_TIMEOUT) -e DEFAULT_WEBHOOK_URL_TIMEOUT=$(DEFAULT_WEBHOOK_URL_TIMEOUT) -e MAXIMUM_WEBHOOK_URL_TIMEOUT=$(MAXIMUM_WEBHOOK_URL_TIMEOUT) -e DEFAULT_LISTEN_PORT=$(DEFAULT_LISTEN_PORT) -e DISABLE_GOOGLE_CHROME=$(DISABLE_GOOGLE_CHROME) -e DISABLE_UNOCONV=$(DISABLE_UNOCONV) -e LOG_LEVEL=$(LOG_LEVEL) -e DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE=$(DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE) -p "$(DEFAULT_LISTEN_PORT):$(DEFAULT_LISTEN_PORT)" $(DOCKER_REGISTRY)/gotenberg:$(VERSION)
|
||||
docker run -it --rm -e MAXIMUM_WAIT_TIMEOUT=$(MAXIMUM_WAIT_TIMEOUT) -e MAXIMUM_WAIT_DELAY=$(MAXIMUM_WAIT_DELAY) -e MAXIMUM_WEBHOOK_URL_TIMEOUT=$(MAXIMUM_WEBHOOK_URL_TIMEOUT) -e DEFAULT_WEBHOOK_URL_TIMEOUT=$(DEFAULT_WEBHOOK_URL_TIMEOUT) -e MAXIMUM_WEBHOOK_URL_TIMEOUT=$(MAXIMUM_WEBHOOK_URL_TIMEOUT) -e DEFAULT_LISTEN_PORT=$(DEFAULT_LISTEN_PORT) -e DISABLE_GOOGLE_CHROME=$(DISABLE_GOOGLE_CHROME) -e DISABLE_UNOCONV=$(DISABLE_UNOCONV) -e LOG_LEVEL=$(LOG_LEVEL) -e ROOT_PATH=$(ROOT_PATH) -e DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE=$(DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE) -p "$(DEFAULT_LISTEN_PORT):$(DEFAULT_LISTEN_PORT)" $(DOCKER_REPOSITORY)/gotenberg:$(VERSION)
|
||||
|
||||
# publish Gotenberg images according to version.
|
||||
publish:
|
||||
|
||||
@@ -23,6 +23,18 @@ You may customize this value with the environment variable `DEFAULT_LISTEN_PORT`
|
||||
|
||||
This environment variable accepts any string that can be turned into a port number.
|
||||
|
||||
## Root path
|
||||
|
||||
By default, the API root path is `/`.
|
||||
|
||||
You may customize this value with the environment variable `ROOT_PATH`.
|
||||
|
||||
This environment variable accepts a string starting and ending with `/`.
|
||||
|
||||
For instance, `/gotenberg/` is a valid value while `gotenberg` is not.
|
||||
|
||||
> This is useful if you wish to do service discovery via URL paths.
|
||||
|
||||
## Disable Google Chrome
|
||||
|
||||
In order to save some resources, the Gotenberg image accepts the environment variable `DISABLE_GOOGLE_CHROME`
|
||||
|
||||
@@ -33,4 +33,4 @@ RUN go mod download &&\
|
||||
# Copy our code source.
|
||||
COPY --chown=gotenberg:gotenberg . .
|
||||
|
||||
CMD ["golangci-lint", "run" ,"--tests=false", "--enable-all", "--disable=dupl", "--disable=funlen" ]
|
||||
CMD ["golangci-lint", "run" ,"--tests=false", "--enable-all", "--disable=dupl", "--disable=funlen", "--disable=wsl", "--disable=gocognit" ]
|
||||
@@ -280,6 +280,22 @@ about what’s going on.</p>
|
||||
|
||||
<p>This environment variable accepts any string that can be turned into a port number.</p>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="environment_variables.root_path" href="#environment_variables.root_path">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Root path</h2>
|
||||
|
||||
<p>By default, the API root path is <code>/</code>.</p>
|
||||
|
||||
<p>You may customize this value with the environment variable <code>ROOT_PATH</code>.</p>
|
||||
|
||||
<p>This environment variable accepts a string starting and ending with <code>/</code>.</p>
|
||||
|
||||
<p>For instance, <code>/gotenberg/</code> is a valid value while <code>gotenberg</code> is not.</p>
|
||||
|
||||
<blockquote>
|
||||
<p>This is useful if you wish to do service discovery via URL paths.</p>
|
||||
</blockquote>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="environment_variables.disable_google_chrome" href="#environment_variables.disable_google_chrome">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Disable Google Chrome</h2>
|
||||
|
||||
@@ -15,31 +15,45 @@ import (
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xtime"
|
||||
)
|
||||
|
||||
const (
|
||||
pingEndpoint string = "/ping"
|
||||
mergeEndpoint string = "/merge"
|
||||
convertGroupEndpoint string = "/convert"
|
||||
htmlEndpoint string = "/html"
|
||||
urlEndpoint string = "/url"
|
||||
markdownEndpoint string = "/markdown"
|
||||
officeEndpoint string = "/office"
|
||||
)
|
||||
func pingEndpoint(config conf.Config) string {
|
||||
return fmt.Sprintf("%s%s", config.RootPath(), "ping")
|
||||
}
|
||||
|
||||
func mergeEndpoint(config conf.Config) string {
|
||||
return fmt.Sprintf("%s%s", config.RootPath(), "merge")
|
||||
}
|
||||
|
||||
func htmlEndpoint(config conf.Config) string {
|
||||
return fmt.Sprintf("%s%s", config.RootPath(), "convert/html")
|
||||
}
|
||||
|
||||
func urlEndpoint(config conf.Config) string {
|
||||
return fmt.Sprintf("%s%s", config.RootPath(), "convert/url")
|
||||
}
|
||||
|
||||
func markdownEndpoint(config conf.Config) string {
|
||||
return fmt.Sprintf("%s%s", config.RootPath(), "convert/markdown")
|
||||
}
|
||||
|
||||
func officeEndpoint(config conf.Config) string {
|
||||
return fmt.Sprintf("%s%s", config.RootPath(), "convert/office")
|
||||
}
|
||||
|
||||
func isMultipartFormDataEndpoint(config conf.Config, path string) bool {
|
||||
var multipartFormDataEndpoints []string
|
||||
multipartFormDataEndpoints = append(multipartFormDataEndpoints, mergeEndpoint)
|
||||
multipartFormDataEndpoints = append(multipartFormDataEndpoints, mergeEndpoint(config))
|
||||
if !config.DisableGoogleChrome() {
|
||||
multipartFormDataEndpoints = append(
|
||||
multipartFormDataEndpoints,
|
||||
fmt.Sprintf("%s%s", convertGroupEndpoint, htmlEndpoint),
|
||||
fmt.Sprintf("%s%s", convertGroupEndpoint, urlEndpoint),
|
||||
fmt.Sprintf("%s%s", convertGroupEndpoint, markdownEndpoint),
|
||||
htmlEndpoint(config),
|
||||
urlEndpoint(config),
|
||||
markdownEndpoint(config),
|
||||
)
|
||||
}
|
||||
if !config.DisableUnoconv() {
|
||||
multipartFormDataEndpoints = append(
|
||||
multipartFormDataEndpoints,
|
||||
fmt.Sprintf("%s%s", convertGroupEndpoint, officeEndpoint),
|
||||
officeEndpoint(config),
|
||||
)
|
||||
}
|
||||
for _, endpoint := range multipartFormDataEndpoints {
|
||||
|
||||
@@ -19,49 +19,51 @@ func TestPingHandler(t *testing.T) {
|
||||
// should return 200.
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint, nil)
|
||||
endpoint := pingEndpoint(config)
|
||||
req := httptest.NewRequest(http.MethodGet, endpoint, nil)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// should return 405 as Method is wrong.
|
||||
req = httptest.NewRequest(http.MethodPost, pingEndpoint, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, endpoint, nil)
|
||||
test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req)
|
||||
}
|
||||
|
||||
func TestMergeHandler(t *testing.T) {
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
endpoint := mergeEndpoint(config)
|
||||
// should return 200.
|
||||
body, contentType := test.MergeMultipartForm(t, nil)
|
||||
req := httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req := httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// should return 405 as Method is wrong.
|
||||
req = httptest.NewRequest(http.MethodGet, mergeEndpoint, nil)
|
||||
req = httptest.NewRequest(http.MethodGet, endpoint, nil)
|
||||
test.AssertStatusCode(t, http.StatusMethodNotAllowed, srv, req)
|
||||
// should return 415 as Content-Type is wrong.
|
||||
body, _ = test.MergeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
test.AssertStatusCode(t, http.StatusUnsupportedMediaType, srv, req)
|
||||
// should return 400 as "waitTimeout" form field
|
||||
// value is < 0.
|
||||
body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "-1"})
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusBadRequest, srv, req)
|
||||
// should return 400 as "waitTimeout" form field
|
||||
// value is is > config.MaximumWaitTimeout().
|
||||
body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "31"})
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusBadRequest, srv, req)
|
||||
// should return 400 as "waitTimeout" form field
|
||||
// value is invalid.
|
||||
body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "not a float"})
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusBadRequest, srv, req)
|
||||
// should return 504.
|
||||
body, contentType = test.MergeMultipartForm(t, map[string]string{string(resource.WaitTimeoutArgKey): "0"})
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusGatewayTimeout, srv, req)
|
||||
}
|
||||
@@ -69,7 +71,7 @@ func TestMergeHandler(t *testing.T) {
|
||||
func TestHTMLHandler(t *testing.T) {
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
endpoint := fmt.Sprintf("%s%s", convertGroupEndpoint, htmlEndpoint)
|
||||
endpoint := htmlEndpoint(config)
|
||||
// should return 200.
|
||||
body, contentType := test.HTMLMultipartForm(t, nil)
|
||||
req := httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
@@ -224,7 +226,7 @@ func TestHTMLHandler(t *testing.T) {
|
||||
func TestURLHandler(t *testing.T) {
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
endpoint := fmt.Sprintf("%s%s", convertGroupEndpoint, urlEndpoint)
|
||||
endpoint := urlEndpoint(config)
|
||||
// should return 200.
|
||||
body, contentType := test.URLMultipartForm(t, nil)
|
||||
req := httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
@@ -379,7 +381,7 @@ func TestURLHandler(t *testing.T) {
|
||||
func TestMarkdownHandler(t *testing.T) {
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
endpoint := fmt.Sprintf("%s%s", convertGroupEndpoint, markdownEndpoint)
|
||||
endpoint := markdownEndpoint(config)
|
||||
// should return 200.
|
||||
body, contentType := test.MarkdownMultipartForm(t, nil)
|
||||
req := httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
@@ -534,7 +536,7 @@ func TestMarkdownHandler(t *testing.T) {
|
||||
func TestOfficeHandler(t *testing.T) {
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
endpoint := fmt.Sprintf("%s%s", convertGroupEndpoint, officeEndpoint)
|
||||
endpoint := officeEndpoint(config)
|
||||
// should return 200.
|
||||
body, contentType := test.OfficeMultipartForm(t, nil)
|
||||
req := httptest.NewRequest(http.MethodPost, endpoint, body)
|
||||
@@ -605,7 +607,7 @@ func TestWebhook(t *testing.T) {
|
||||
srv := New(config)
|
||||
// our custom server should receive the PDF.
|
||||
body, contentType := test.MergeMultipartForm(t, map[string]string{string(resource.WebhookURLArgKey): "http://localhost:3001/foo"})
|
||||
req := httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req := httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
err := <-status
|
||||
@@ -616,7 +618,7 @@ func TestResultFilename(t *testing.T) {
|
||||
config := conf.DefaultConfig()
|
||||
srv := New(config)
|
||||
body, contentType := test.MergeMultipartForm(t, map[string]string{string(resource.ResultFilenameArgKey): "foo.pdf"})
|
||||
req := httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req := httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
rec := httptest.NewRecorder()
|
||||
srv.ServeHTTP(rec, req)
|
||||
|
||||
@@ -30,7 +30,7 @@ func contextMiddleware(config conf.Config) echo.MiddlewareFunc {
|
||||
// there is no need to create a Resource.
|
||||
if !isMultipartFormDataEndpoint(config, ctx.Path()) {
|
||||
// validate method for healthcheck endpoint.
|
||||
if ctx.Path() == pingEndpoint && ctx.Request().Method != http.MethodGet {
|
||||
if ctx.Path() == pingEndpoint(config) && ctx.Request().Method != http.MethodGet {
|
||||
err := doErr(ctx, echo.NewHTTPError(http.StatusMethodNotAllowed))
|
||||
return ctx.LogRequestResult(err, false)
|
||||
}
|
||||
@@ -60,14 +60,14 @@ func contextMiddleware(config conf.Config) echo.MiddlewareFunc {
|
||||
}
|
||||
|
||||
// loggerMiddleware logs the result of a request.
|
||||
func loggerMiddleware() echo.MiddlewareFunc {
|
||||
func loggerMiddleware(config conf.Config) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
ctx := context.MustCastFromEchoContext(c)
|
||||
err := next(ctx)
|
||||
// we do not want to log healthcheck requests if
|
||||
// log level is not set to DEBUG.
|
||||
isDebug := ctx.Path() == pingEndpoint
|
||||
isDebug := ctx.Path() == pingEndpoint(config)
|
||||
return ctx.LogRequestResult(err, isDebug)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,22 +11,21 @@ func New(config conf.Config) *echo.Echo {
|
||||
srv.HideBanner = true
|
||||
srv.HidePort = true
|
||||
srv.Use(contextMiddleware(config))
|
||||
srv.Use(loggerMiddleware())
|
||||
srv.Use(loggerMiddleware(config))
|
||||
srv.Use(cleanupMiddleware())
|
||||
srv.Use(errorMiddleware())
|
||||
srv.GET(pingEndpoint, pingHandler)
|
||||
srv.POST(mergeEndpoint, mergeHandler)
|
||||
srv.GET(pingEndpoint(config), pingHandler)
|
||||
srv.POST(mergeEndpoint(config), mergeHandler)
|
||||
if config.DisableGoogleChrome() && config.DisableUnoconv() {
|
||||
return srv
|
||||
}
|
||||
g := srv.Group(convertGroupEndpoint)
|
||||
if !config.DisableGoogleChrome() {
|
||||
g.POST(htmlEndpoint, htmlHandler)
|
||||
g.POST(urlEndpoint, urlHandler)
|
||||
g.POST(markdownEndpoint, markdownHandler)
|
||||
srv.POST(htmlEndpoint(config), htmlHandler)
|
||||
srv.POST(urlEndpoint(config), urlHandler)
|
||||
srv.POST(markdownEndpoint(config), markdownHandler)
|
||||
}
|
||||
if !config.DisableUnoconv() {
|
||||
g.POST(officeEndpoint, officeHandler)
|
||||
srv.POST(officeEndpoint(config), officeHandler)
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package xhttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
@@ -28,31 +27,31 @@ func TestDisableChromeEndpoints(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
srv := New(config)
|
||||
// Ping endpoint should return 200.
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint, nil)
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Merge endpoint should return 200.
|
||||
body, contentType := test.MergeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// HTML endpoint should return 404.
|
||||
body, contentType = test.HTMLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, htmlEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// URL endpoint should return 404.
|
||||
body, contentType = test.URLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, urlEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// Markdown endpoint should return 404.
|
||||
body, contentType = test.MarkdownMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, markdownEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// Office endpoint should return 200.
|
||||
body, contentType = test.OfficeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, officeEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// finally...
|
||||
@@ -65,31 +64,31 @@ func TestDisableUnoconvEndpoints(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
srv := New(config)
|
||||
// Ping endpoint should return 200.
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint, nil)
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Merge endpoint should return 200.
|
||||
body, contentType := test.MergeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// HTML endpoint should return 200.
|
||||
body, contentType = test.HTMLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, htmlEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// URL endpoint should return 200.
|
||||
body, contentType = test.URLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, urlEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Markdown endpoint should return 200.
|
||||
body, contentType = test.MarkdownMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, markdownEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Office endpoint should return 404.
|
||||
body, contentType = test.OfficeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, officeEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// finally...
|
||||
@@ -102,34 +101,71 @@ func TestDisableChromeAndUnoconvEndpoints(t *testing.T) {
|
||||
assert.Nil(t, err)
|
||||
srv := New(config)
|
||||
// Ping endpoint should return 200.
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint, nil)
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Merge endpoint should return 200.
|
||||
body, contentType := test.MergeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint, body)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// HTML endpoint should return 404.
|
||||
body, contentType = test.HTMLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, htmlEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// URL endpoint should return 404.
|
||||
body, contentType = test.URLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, urlEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// Markdown endpoint should return 404.
|
||||
body, contentType = test.MarkdownMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, markdownEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// Office endpoint should return 404.
|
||||
body, contentType = test.OfficeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", convertGroupEndpoint, officeEndpoint), body)
|
||||
req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusNotFound, srv, req)
|
||||
// finally...
|
||||
os.Setenv(conf.DisableGoogleChromeEnvVar, "0")
|
||||
os.Setenv(conf.DisableUnoconvEnvVar, "0")
|
||||
}
|
||||
|
||||
func TestCustomRootPath(t *testing.T) {
|
||||
os.Setenv(conf.RootPathEnvVar, "/foo/")
|
||||
config, err := conf.FromEnv()
|
||||
assert.Nil(t, err)
|
||||
srv := New(config)
|
||||
// Ping endpoint should return 200.
|
||||
req := httptest.NewRequest(http.MethodGet, pingEndpoint(config), nil)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Merge endpoint should return 200.
|
||||
body, contentType := test.MergeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, mergeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// HTML endpoint should return 200.
|
||||
body, contentType = test.HTMLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, htmlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// URL endpoint should return 200.
|
||||
body, contentType = test.URLMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, urlEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Markdown endpoint should return 200.
|
||||
body, contentType = test.MarkdownMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, markdownEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// Office endpoint should return 200.
|
||||
body, contentType = test.OfficeMultipartForm(t, nil)
|
||||
req = httptest.NewRequest(http.MethodPost, officeEndpoint(config), body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
test.AssertStatusCode(t, http.StatusOK, srv, req)
|
||||
// finally...
|
||||
os.Setenv(conf.RootPathEnvVar, "/")
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ const (
|
||||
// LogLevelEnvVar contains the name
|
||||
// of the environment variable "LOG_LEVEL".
|
||||
LogLevelEnvVar string = "LOG_LEVEL"
|
||||
// RootPathEnvVar contains the name
|
||||
// of the environment variable "ROOT_PATH".
|
||||
RootPathEnvVar string = "ROOT_PATH"
|
||||
// DefaultGoogleChromeRpccBufferSizeEnvVar contains the name
|
||||
// of the environment variable "DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE".
|
||||
DefaultGoogleChromeRpccBufferSizeEnvVar string = "DEFAULT_GOOGLE_CHROME_RPCC_BUFFER_SIZE"
|
||||
@@ -51,6 +54,7 @@ type Config struct {
|
||||
disableGoogleChrome bool
|
||||
disableUnoconv bool
|
||||
logLevel xlog.Level
|
||||
rootPath string
|
||||
maximumGoogleChromeRpccBufferSize int64
|
||||
defaultGoogleChromeRpccBufferSize int64
|
||||
}
|
||||
@@ -68,6 +72,7 @@ func DefaultConfig() Config {
|
||||
disableGoogleChrome: false,
|
||||
disableUnoconv: false,
|
||||
logLevel: xlog.InfoLevel,
|
||||
rootPath: "/",
|
||||
maximumGoogleChromeRpccBufferSize: 104857600, // ~100 MB
|
||||
defaultGoogleChromeRpccBufferSize: 1048576, // 1 MB
|
||||
}
|
||||
@@ -163,6 +168,16 @@ func FromEnv() (Config, error) {
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
rootPath, err := xassert.StringFromEnv(
|
||||
RootPathEnvVar,
|
||||
c.rootPath,
|
||||
xassert.StringStartWith("/"),
|
||||
xassert.StringEndWith("/"),
|
||||
)
|
||||
c.rootPath = rootPath
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
defaultGoogleChromeRpccBufferSize, err := xassert.Int64FromEnv(
|
||||
DefaultGoogleChromeRpccBufferSizeEnvVar,
|
||||
c.defaultGoogleChromeRpccBufferSize,
|
||||
@@ -242,6 +257,12 @@ func (c Config) LogLevel() xlog.Level {
|
||||
return c.logLevel
|
||||
}
|
||||
|
||||
// RootPath returns the rooth path from
|
||||
// the configuration.
|
||||
func (c Config) RootPath() string {
|
||||
return c.rootPath
|
||||
}
|
||||
|
||||
// MaximumGoogleChromeRpccBufferSize returns the maximum
|
||||
// Google Chrome rpcc buffer size from the configuration.
|
||||
func (c Config) MaximumGoogleChromeRpccBufferSize() int64 {
|
||||
|
||||
@@ -320,6 +320,29 @@ func TestLogLevelFromEnv(t *testing.T) {
|
||||
os.Unsetenv(LogLevelEnvVar)
|
||||
}
|
||||
|
||||
func TestRootPathFromEnv(t *testing.T) {
|
||||
var (
|
||||
expected Config
|
||||
result Config
|
||||
err error
|
||||
)
|
||||
// ROOT_PATH correctly set.
|
||||
os.Setenv(RootPathEnvVar, "/foo/")
|
||||
expected = DefaultConfig()
|
||||
expected.rootPath = "/foo/"
|
||||
result, err = FromEnv()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, expected, result)
|
||||
os.Unsetenv(RootPathEnvVar)
|
||||
// ROOT_PATH wrongly set.
|
||||
os.Setenv(RootPathEnvVar, "foo")
|
||||
expected = DefaultConfig()
|
||||
result, err = FromEnv()
|
||||
test.AssertError(t, err)
|
||||
assert.Equal(t, expected, result)
|
||||
os.Unsetenv(RootPathEnvVar)
|
||||
}
|
||||
|
||||
func TestDefaultGoogleChromeRpccBufferSizeFromEnv(t *testing.T) {
|
||||
var (
|
||||
expected Config
|
||||
@@ -368,6 +391,7 @@ func TestGetters(t *testing.T) {
|
||||
assert.Equal(t, result.disableGoogleChrome, result.DisableGoogleChrome())
|
||||
assert.Equal(t, result.disableUnoconv, result.DisableUnoconv())
|
||||
assert.Equal(t, result.logLevel, result.LogLevel())
|
||||
assert.Equal(t, result.rootPath, result.RootPath())
|
||||
assert.Equal(t, result.maximumGoogleChromeRpccBufferSize, result.MaximumGoogleChromeRpccBufferSize())
|
||||
assert.Equal(t, result.defaultGoogleChromeRpccBufferSize, result.DefaultGoogleChromeRpccBufferSize())
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package xassert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/xerror"
|
||||
)
|
||||
@@ -54,7 +55,67 @@ func StringOneOf(values []string) RuleString {
|
||||
}
|
||||
}
|
||||
|
||||
type ruleStringStartWith struct {
|
||||
*baseRuleString
|
||||
startWith string
|
||||
}
|
||||
|
||||
func (r ruleStringStartWith) validate() error {
|
||||
const op string = "xassert.ruleStringStartWith.validate"
|
||||
if strings.HasPrefix(r.value, r.startWith) {
|
||||
return nil
|
||||
}
|
||||
return xerror.Invalid(
|
||||
op,
|
||||
fmt.Sprintf("'%s' should start with '%s', got '%s'", r.key, r.startWith, r.value),
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
StringStartWith returns a RuleString for
|
||||
validating that a string starts with
|
||||
given string.
|
||||
*/
|
||||
func StringStartWith(startWith string) RuleString {
|
||||
return ruleStringStartWith{
|
||||
&baseRuleString{},
|
||||
startWith,
|
||||
}
|
||||
}
|
||||
|
||||
type ruleStringEndWith struct {
|
||||
*baseRuleString
|
||||
endWith string
|
||||
}
|
||||
|
||||
func (r ruleStringEndWith) validate() error {
|
||||
const op string = "xassert.ruleStringEndWith.validate"
|
||||
if strings.HasSuffix(r.value, r.endWith) {
|
||||
return nil
|
||||
}
|
||||
return xerror.Invalid(
|
||||
op,
|
||||
fmt.Sprintf("'%s' should end with '%s', got '%s'", r.key, r.endWith, r.value),
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
StringEndWith returns a RuleString for
|
||||
validating that a string ends with
|
||||
given string.
|
||||
*/
|
||||
func StringEndWith(endWith string) RuleString {
|
||||
return ruleStringEndWith{
|
||||
&baseRuleString{},
|
||||
endWith,
|
||||
}
|
||||
}
|
||||
|
||||
// Compile-time checks to ensure type implements desired interfaces.
|
||||
var (
|
||||
_ = RuleString(new(ruleStringOneOf))
|
||||
_ = RuleString(new(ruleStringStartWith))
|
||||
_ = RuleString(new(ruleStringEndWith))
|
||||
)
|
||||
|
||||
@@ -18,3 +18,27 @@ func TestStringOfOne(t *testing.T) {
|
||||
err = rule.validate()
|
||||
test.AssertError(t, err)
|
||||
}
|
||||
|
||||
func TestStringStartWith(t *testing.T) {
|
||||
rule := StringStartWith("foo")
|
||||
// should be OK.
|
||||
rule.with("FOO", "foobarfoo")
|
||||
err := rule.validate()
|
||||
assert.Nil(t, err)
|
||||
// should not be OK.
|
||||
rule.with("FOO", "qux")
|
||||
err = rule.validate()
|
||||
test.AssertError(t, err)
|
||||
}
|
||||
|
||||
func TestStringEndWith(t *testing.T) {
|
||||
rule := StringEndWith("foo")
|
||||
// should be OK.
|
||||
rule.with("FOO", "foobarfoo")
|
||||
err := rule.validate()
|
||||
assert.Nil(t, err)
|
||||
// should not be OK.
|
||||
rule.with("FOO", "qux")
|
||||
err = rule.validate()
|
||||
test.AssertError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user