Issue in publishing swagger doc for google cloud endpoints - google-cloud-endpoints

I am trying to publish Swagger documentation for my cloud endpoints. My application is in Python. As per the documentation [1]:
1.) I downloaded the repository from https://github.com/swagger-api/swagger-ui.git.
2.) Copied the dist directory from the downloaded repository and placed into the docs folder inside my project. I created a new folder with name docs.
3,) As per the step 3, the project name should be FQDN. The project name I have in openapi.yaml is-> host: "sample-project-******.appspot.com"
4.) As given in step 4 in the documentation, I added following in app.yaml
handlers:
- url: /docs
static_files: docs/index.html
upload: docs/index.html
- url: /docs/(.*)
static_files: docs/\1
upload: docs/.
5.) Updated the URL entry in docs/index.html with the following:
url = "../api-docs";
6.) Added following in openapi.yaml
"/docs":
get:
description: "Documentation"
operationId: "docs"
produces:
- "application/json"
responses:
200:
description: "Documentation"
Questions:
What is the significance of adding url = "../api-docs" in step 5?
When I am hitting /docs, I am getting 404.
[1] https://cloud.google.com/endpoints/docs/openapi/adding-swagger

In regards to adding "url", from the documentation at https://cloud.google.com/endpoints/docs/openapi/adding-swagger:
This directs the Swagger UI to retrieve your OpenApi spec from this URL. Add a handler for this path which reads your openapi.yaml and serves it as json.
Also, for exposing your Swagger documentation, you might want to consider that Endpoints is working on a developer portal feature and looking for users: https://cloudplatform.googleblog.com/2018/03/now-you-can-automatically-document-your-API-with-Cloud-Endpoints.html

Related

How can i add an HTTP header in my app on App Engine?

I have an Angular app running on App Engine and for security reasons i need to add some headers to server responses, for example the HSTS header. Checking on the App Engine documentation i found that apparently you can do it by adding the following lines in your app.yaml file:
handlers:
- url: /images
static_dir: static/images
http_headers:
X-Foo-Header: foo
X-Bar-Header: bar value
vary: Accept-Encoding
# ...
However, this is not adding headers to my response after adding those lines to my app.yaml file.
Can you help me to find out what am i doing wrong? I am new on App Engine Configurations.
Thanks in advance

Google App Engine Flex: Wordpress Plugin's Read/Write File Permissions

We are trying to see if Google App Engine will be a good fit for our Wordpress Sites. I just ran into an issue with a plugin that needs to have a folder with read/write/execute permissions.
"All in One WP Migration is not able to create /app/wordpress/wp-content/plugins/all-in-one-wp-migration/storage folder. You will need to create this folder and grant it read/write/execute permissions (0777) for the All in One WP Migration plugin to function properly."
I noticed in order to upload media files, you need to activate the Google Cloud Storage plugin. So this takes care of that issue, but how should I handle plugins and other I/O?
I thought using Flex instead of Standard would fix this.
App.yaml
runtime: php
env: flex
beta_settings:
cloud_sql_instances: my-project:us-east4:test-instance
runtime_config:
document_root: wordpress
env_variables:
WHITELIST_FUNCTIONS: escapeshellarg,escapeshellcmd,exec,pclose,popen,shell_exec,phpversion,php_uname
php.ini
extension=bcmath.so
extension=gd.so
zend_extension=opcache.so
short_open_tag=On
google_app_engine.disable_readonly_filesystem = 1
EDIT:
I found something to put in app.yaml HOWEVER I don't know if this should be something on production
In the runtime_config I added
skip_lockdown_document_root: true
I'd like to know if this acceptable to put on a live site.
I also put:
handlers:
- url: /(.*\.(htm|html|css|js))$
static_files: wordpress/\1
upload: wordpress/.*\.(htm|html|css|js)$
application_readable: true
- url: /wp-content/(.*\.(ico|jpg|jpeg|png|gif|woff|ttf|otf|eot|svg))$
static_files: wordpress/wp-content/\1
upload: wordpress/wp-content/.*\.(ico|jpg|jpeg|png|gif|woff|ttf|otf|eot|svg)$
application_readable: true
- url: /(.*\.(ico|jpg|jpeg|png|gif|woff|ttf|otf|eot|svg))$
static_files: wordpress/\1
upload: wordpress/.*\.(ico|jpg|jpeg|png|gif|woff|ttf|otf|eot|svg)$
application_readable: true
- url: /wp-includes/images/media/(.*\.(ico|jpg|jpeg|png|gif|woff|ttf|otf|eot|svg))$
static_files: wordpress/wp-includes/images/media/\1
upload: wordpress/wp-includes/images/media/.*\.(ico|jpg|jpeg|png|gif|woff|ttf|otf|eot|svg)$
application_readable: true
- url: /wp-admin/(.+)
script: wordpress/wp-admin/\1
secure: always
- url: /wp-admin/
script: wordpress/wp-admin/index.php
secure: always
- url: /wp-login.php
script: wordpress/wp-login.php
secure: always
- url: /wp-cron.php
script: wordpress/wp-cron.php
login: admin
- url: /xmlrpc.php
script: wordpress/xmlrpc.php
- url: /wp-(.+).php
script: wordpress/wp-\1.php
- url: /(.+)?/?
script: wordpress/index.php
If you want to use standard, there's the limitation that GAE apps can't write to the filesystem.
If the plugin requires to write to the filesystem, then you should use flex.
Even when using flex, whatever is written in the filesystem will not be persisted as the only current storage option is to create a ramdisk in the instance, but the data stored there is not shared among instances, and will be lost on instance death.
There seems to be some workaround to use GCSfuse to mount a somewhat persistent storage in GAE flex, but I would not suggest it as you would run into concurrent write issues.
To summarize, if you need to read and write data into a persistent storage shared between all the instances, GAE is not the solution for you. After all, the whole point of serverless is the idempotence of executions. If your app depends on locally stored files (as this Wordpress plugin seems to do), then the result of the execution will depend on what instance is handling the request.

PrestaSitemap bundle generates localhost on production server

I'm using Presta SiteMap Bundle for generating sitemaps on my site, but when it generates to me sitemaps on prod server path to sitemaps looks like below:
http://localhost/sitemap.holidayideas.xml
What should I write in config or anywhere in my app to generate correct url's for my sitemaps.
P.S. I'm using Symfony 3.3.2 for my app
I found the solution - need to specify url and protocol in parameters.yml as below:
# app/config/parameters.yml
parameters:
router.request_context.host: your-domain.com
router.request_context.scheme: http

Google Cloud Endpoints + Firebase Auth: method_info is not set

So I am running the sample code provided by Google:
package com.neat.backend;
/**
* An endpoint class we are exposing
*/
#Api(
name = "myApi",
version = "v1",
namespace = #ApiNamespace(
ownerDomain = "backend.neat.com",
ownerName = "backend.neat.com",
packagePath = ""
),
issuers = {
#ApiIssuer(
name = "firebase",
issuer = "https://securetoken.google.com/" + PROJECT_ID,
jwksUri = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com")
})
public class MyEndpoint {
#ApiMethod(
path = "firebase_user",
httpMethod = ApiMethod.HttpMethod.GET,
authenticators = {EspAuthenticator.class},
issuerAudiences = {#ApiIssuerAudience(name = "firebase", audiences = {PROJECT_ID})}
)
public Email getUserEmailFirebase(User user) throws UnauthorizedException {
if (user == null) {
throw new UnauthorizedException("Invalid credentials");
}
Email response = new Email(user.getEmail());
return response;
}
}
I am getting a Firebase token from my Android client and try to send it to the backend by:
curl -H "Authorization: Bearer FIREBASE_JWT_TOKEN" \
-X GET \
http://localhost:8080/_ah/api/echo/v1/firebase_user
The error I see in the logs is the following:
[INFO] java.lang.IllegalStateException: method_info is not set in the request
[INFO] at com.google.api.server.spi.auth.EspAuthenticator.authenticate(EspAuthenticator.java:67)
[INFO] at com.google.api.server.spi.request.Auth.authenticate(Auth.java:100)
[INFO] at com.google.api.server.spi.request.ServletRequestParamReader.getUser(ServletRequestParamReader.java:191)
[INFO] at com.google.api.server.spi.request.ServletRequestParamReader.deserializeParams(ServletRequestParamReader.java:136)
[INFO] at com.google.api.server.spi.request.RestServletRequestParamReader.read(RestServletRequestParamReader.java:123)
[INFO] at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:350)
[INFO] at com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler.handle(EndpointsMethodHandler.java:114)
[INFO] at com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler.handle(EndpointsMethodHandler.java:102)
[INFO] at com.google.api.server.spi.dispatcher.PathDispatcher.dispatch(PathDispatcher.java:49)
[INFO] at com.google.api.server.spi.EndpointsServlet.service(EndpointsServlet.java:71)
[INFO] at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
I have tried deploying the exact same code to App Engine and it works perfectly. I have tried debugging EspAuthenticator and it seems that it is expecting the Servlet filters to inject some attributes in the request.
It took me a while and a bit of debugging to realize that the filter that is supposed to inject method_info was not being fired.
I could fix it by modifying the mapping in web.xml adding the following dispatcher tags:
<filter-mapping>
<filter-name>endpoints-api-configuration</filter-name>
<servlet-name>EndpointsServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
generat and deploy the OpenAPI configuration file
$ mvn clean package endpoints-framework:openApiDocs -DskipTests
$ gcloud endpoints services deploy target/openapi-docs/openapi.json
$ mvn appengine:run
I got the same error message, and eventually tracked it down to making a request with a trailing / in the URL where my API did not specify one. The trailing slash only causes an error for calls that provide an authorization token.
Apparently ControlFilter (and therefore also GoogleAppEngineControlFilter) did not recognize it as a valid endpoint and therefore did not bother attaching method_info to the request. But then EndpointsServlet thought it was valid and tried to authenticate without all the needed info!
The fix was easy: remove the trailing slash from the URL in my request. Tracking down the problem, however, was not! I see this was not your problem, but maybe this answer will help someone else.
#Kevendra's answer highlights that this issue can be caused if an openapi.json file is missing a reference to the endpoint API method. Firebase may be using this to reference and discover the API method.
From the Google OpenAPI Overview:
Basic structure of an OpenAPI document:
An OpenAPI document describes
the surface of your REST API, and defines information such as:
The name and description of the API. The individual endpoints (paths)
in the API. How the callers are authenticated.
Follow these steps to regenerate and deploy the openapi.json file:
generate:
$ mvn clean package endpoints-framework:openApiDocs -DskipTests
mvn clean - run a Maven goal to clean your project. package - compile and package it
endpoints-framework:openApiDocs generate OpenAPI documents. This will generate the openapi.json file at the location: target/openapi-docs/openapi.json- see generating and deploying an api configuration.
-DskipTests skips running any tests, to avoid any test failure due
to the openapi.json not yet being generated
deploy:
(As a precaution you can first validate the project ID returned from the following command to make sure that the service isn't created in the wrong project - gcloud config list project)
$ gcloud endpoints services deploy target/openapi-docs/openapi.json
Deploys the openapi.json file from its generated location (in the 'generate' step above). See the Google docs on Deploying the OpenAPI document

Google App Engine modules: routing second module to subdirectory

Has anyone run two different WordPress installations as separate modules inside Google App Engine?
I have the following:
/app/
- wordpress1
- wordpress2
- app.yaml
- second.yaml
- dispatch.yaml
- php.ini
Inside wordpress1 and wordpress2 are somewhat clean installations of WordPress, with some GAE helper plugins.
app.yaml contains the default module config, which redirects traffic to wordpress1 using URL handlers.
second.yaml contains the second module config (module: second) and redirects traffic to wordpress2.
In dispatch.yaml I only check for a subdir second to load the second.yaml config:
dispatch:
- url: "*/second*"
module: second
Everything is fine and dandy:
http://localhost.dev:8080 -> wordpress1/index.php
http://localhost.dev:8080/second/ -> wordpress2/index.php
But I can't seem to work out how to set the edge cases:
http://localhost.dev:8080/secondwithextra -> dispatcher error (no URL set)
http://localhost.dev:8080/second (missing trailing slash) -> same as above
I tried to add the following to second.yaml handlers:
- url: /second[^/].+/?
script: wordpress1/index.php # Reroute to `wordpress1` because not a directory match.
But that didn't really work out.
How can I make the second module accept request URI /second, /second/, /second/abc but not /secondxyz?
Having the dispatch.yaml URL glob set to */second/* breaks the slashless /second.
I think you could try to add both */second/* and /second in dispatch.yaml.

Resources