I have two cloud run services (Next.js and API server) and I want to serve them through a single endpoint.
I want requests to /api to be forwarded to API service and all other other requests (/*) to be forwarded to Next.js server.
Cloud Run documentation suggests that I use Endpoint but it does not seem to support wildcard paths.
What are the possible alternatives?
Google API Gateway supports different wildcards, I'using Google Functions as backend, but that shouldn't make a different when using the GW with Google Run.
My scenario:
/ should route to the /index.html
/assets should route to the /assets/any-file-here.png
/logo-256.png should route to the /logo-256.png
/endpoint-1 should route only to the API, but hosted on another function
/endpoint-2/some-param should route only to the API, hosted on the same function as the assets
With this configuration everything get's routed liked wanted, using Double Wildcard Matching.
It doesn't matter that the wildcard is before specific routes, this is handled correctly by the gateway.
{
"swagger": "2.0",
"info": {
"version": "0.0.1",
"title": "Some API w/ Assets"
},
"paths": {
"/": {
"get": {
"summary": "home",
"operationId": "home",
"parameters": [],
"x-google-backend": {
"address": "https://THE-GOOGLE-RUN-OR-FUNCTION",
"path_translation": "CONSTANT_ADDRESS"
},
"responses": {
"200": {
"description": "Home"
}
}
}
},
"/{files=**}": {
"get": {
"summary": "assets",
"operationId": "assets",
"parameters": [
{
"in": "path",
"name": "files",
"type": "string",
"required": true
}
],
"x-google-backend": {
"address": "https://THE-GOOGLE-RUN-OR-FUNCTION",
"path_translation": "APPEND_PATH_TO_ADDRESS"
},
"responses": {
"200": {
"description": "assets"
}
}
}
},
"/endpoint-1": {
"get": {
"summary": "Some pure backend api",
"operationId": "ep1",
"x-google-backend": {
"address": "https://SOME-OTHER-GOOGLE-RUN-OR-FUNCTION",
"path_translation": "APPEND_PATH_TO_ADDRESS"
},
"parameters": [],
"responses": {
"200": {
"description": "result values"
}
}
}
},
"/endpoint-2/{some_param}": {
"get": {
"summary": "Some pure backend API with path param",
"operationId": "ep2",
"parameters": [
{
"in": "path",
"name": "some_param",
"type": "string",
"required": true
}
],
"x-google-backend": {
"address": "https://THE-GOOGLE-RUN-OR-FUNCTION",
"path_translation": "APPEND_PATH_TO_ADDRESS"
},
"responses": {
"200": {
"description": "result values"
}
}
}
}
}
}
But with this setup, your page won't be that fast, I recommend adding Google Load Balancer with Google CDN before your API gateway when you are serving files.
This is best addressed through the usage of Firebase hosting since they have a tutorial to do just this.
Hope you find this useful
Related
Is there a mechanism in Swashbuckle that can prevent definitions from being created with referencing to them in parameters/responses/etc.?
By default, you might get a path that looks like this:
"/profile": {
"get": {
"summary": "Get my profile details.",
"produces": [
"application/json",
],
"parameters": [],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/ProfileModel"
}
}
}
}
}
But what I'd like is for it to expand the schema inline like this:
"/profile": {
"get": {
"summary": "Get my profile details.",
"produces": [
"application/json",
],
"parameters": [],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "id"
},
"firstName": {
"type": "string",
"description": "firstName"
},
"surname": {
"type": "string",
"description": "surname"
},
"emailAddress": {
"type": "string",
"description": "emailAddress"
}
}
}
}
}
}
}
I reviewed this StackOverflow question and I don't think it's what I'm looking for (or maybe misinterpreted).
Taken a look through the Swashbuckle README to understand its capabilities but coming up short. Any help here would be most appreciated.
For additional context, looking at the Swashbuckle PDF documentation in section 1.7, I essentially want to bypass or revert the action they describe as
automatically generating a corresponding schema for user-defined reference types and reference the definition via the $ref keyword.
Digging into the codebase a little, it looks like it's not possible at the moment.
However, you can create a custom ISchemaGenerator from the one in source and alter the GenerateConcreteSchema method under the DataType.Object case to not return as reference and this solves the issue.
I am using Ocelot gateway and for swagger document using "MMLib.SwaggerForOcelot" library.
For some swagger Key, swagger UI is showing "No operations defined in spec!" and swagger JSON is coming without paths like
{
"openapi": "3.0.1",
"info": {
"title": "Admin API",
"version": "v1"
},
"paths": {},
"components": {
"schemas": {}
}
}
Ocelot Configuration Route is
{
"DownstreamPathTemplate": "/api/admin/v{version}/{everything} ",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
"UpstreamPathTemplate": "/api/admin/v{version}/{everything}",
"UpstreamHttpMethod": [],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 1000,
"TimeoutValue": 900000
},
"SwaggerKey": "AdminAPI"
}
and Swagger Configuration is
"SwaggerEndPoints": [
{
"Key": "AdminAPI",
"Config": [
{
"Name": "Admin API",
"Version": "v1",
"Url": "http://localhost:5000/swagger/v1/swagger.json"
}
]
}
]
after reviewing the MMLib.SwaggerForOcelot source code, it looks like something to do with the version in the downstream path, any clue on how this can be fixed?
The issue is that MMLib.SwaggerForOcelot is not considering {version} while doing Ocelot transformation.
RouteOptions has a property TransformByOcelotConfig which is set to true by default, so once swagger JSON is obtained from downstream, the transformation will be done.
here, it will try to find the route from the route configuration like below and if not found it will delete the route from swagger JSON
private static RouteOptions FindRoute(IEnumerable<RouteOptions> routes, string downstreamPath, string basePath)
{
string downstreamPathWithBasePath = PathHelper.BuildPath(basePath, downstreamPath);
return routes.FirstOrDefault(p
=> p.CanCatchAll
? downstreamPathWithBasePath.StartsWith(p.DownstreamPathWithSlash, StringComparison.CurrentCultureIgnoreCase)
: p.DownstreamPathWithSlash.Equals(downstreamPathWithBasePath, StringComparison.CurrentCultureIgnoreCase));
}
The problem is StartsWith will return false since swagger JSON path will be like
/api/admin/v{version}/Connections
and route config is like
/api/admin/v{version}/{everything}
and version will replace with the version given in swagger options so that it will become
/api/admin/v1/{everything}
Fix to this problem will be
Either set "TransformByOcelotConfig":false in swagger option
"SwaggerEndPoints": [
{
"Key": "AdminAPI",
"TransformByOcelotConfig":false,
"Config": [
{
"Name": "Admin API",
"Version": "v1",
"Url": "http://localhost:5000/swagger/v1/swagger.json"
}
]
}
]
Or Change the route, just to have {everything} keyword
{
"DownstreamPathTemplate": "/api/admin/{everything} ",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
"UpstreamPathTemplate": "/api/admin/{everything}",
"UpstreamHttpMethod": [],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 1000,
"TimeoutValue": 900000
},
"SwaggerKey": "AdminAPI"
}
I am trying to setup an own App in Integromat
What is required for my App is an URL (and later a Bearer Token) to be entered manually by the user who wants to use my App.
I have the Apps Base:
{
"baseUrl": "{{connection.url}}",
"log": {
"sanitize": ["request.headers.authorization"]
}
}
a Connection:
Parameters:
[
{
"name": "url",
"label": "url",
"type": "text",
"required": true,
"value":"https://my-server"
}
]
and the Scenario:
{
"url": "/api/endpoint",
"method": "GET",
"qs": {},
"headers": "{{connection.headers}}",
"response": {
"output": "{{body}}"
}
}
When i execute, the scenario from my App. The URL seems not to be correctly taken over from the one configured inside the connection parametrs.
Can someone help?
Everything was right. I had to delete the old Connection and create a new one.
I am trying to create swagger json and trying to check it's validity in
http://editor.swagger.io
Upon validating the json, the above mentioned editor gives the following error:
Schema error should NOT have additional properties
additionalProperty: components
Jump to line 0
If for some reason I can't define an element named components at root level where i am going to have some sort of json schema, what is the right way to do a $ref on the schema for requestBody for an API operation as I intend to do as seen in my example below. Also, do you see anything wrong with my swagger json ?
My swagger json for swagger2.0 look like this.
{
"swagger": "2.0",
"info": {
"version": "1.0",
"title": "My swagger API",
"contact": {
"name": "myName",
"email": "abc#gmail.com"
}
},
"host": "localhost:1234",
"basePath": "/",
"tags": [{
"name": "someTagName",
"description": "this is a try"
}],
"components":{"schemas": {"myEndPoint": ""}},
"paths": {
"/myEndPoint": {
"post": {
"tags": ["some-tag"],
"summary": "myEndPoint endpoint will give you something",
"description": "some description will go here",
"operationId": "getMyEndPoint",
"consumes": ["application/json"],
"produces": ["application/json"],
"parameters": [{
"in": "body",
"name": "somePayload",
"description": "somePayload is what this is",
"required": true,
"schema": {
"$ref": "#components/schemas/myEndPoint"
}
},
{
"in": "header",
"name": "Authorization",
"description": "auth token goes here",
"required": true,
"type": "string"
}],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "string"
}
},
"400": {
"description": "Bad Request"
}
}
}
}
}
}
You are mixing up OpenAPI 3.0 and 2.0 syntax. The components keyword is used in OpenAPI 3.0. In OpenAPI/Swagger 2.0, reusable schemas live under definitions:
"definitions": {
"myEndPoint": {
...
}
}
Make sure to also change the $ref to
"$ref": "#/definitions/myEndPoint"
I created an intent with slots in Alexa. This triggers an AWS lambda written in Python. I am logging the 'event'. I expect event['request']['dialogState'] to be present but it is not. Am I missing something?
Event:
{u'session': {u'application': {u'applicationId': u'amzn1.ask.skill.b2a191bb-7ee2-4fa7-aa7b-456d4bd2ee35'}, u'sessionId': u'Sessi onId.afb747ea-01ae-4094-ba10-ac49405a99df', u'user': {u'userId': u'amzn1.ask.account.BFHTSNCIVD2HA563BEPLRW5TSCESQEZXCIULPPB2ULOZBIJRCPM 5Z5NWOWH3HWNOZRTY4WT3FZFVGWWPKRSKC4ZNDSB2EYB45TYQ3RNY67CZPGF4GBMV6CL57C5MJVPIQPH25DQWGXGALDBCBRHMG5IA3Y26UHI7MHPIV3665ZU5OESS3UBADD7MDYQ BWJZFB3XHJS6IM2Y5UTQ', u'accessToken': None}, u'new': False, u'attributes': {}}, u'request': {u'locale': u'en-US', u'type': u'IntentRequ est', u'intent': {u'slots': {u'ncpu': {u'name': u'ncpu'}, u'nmem': {u'name': u'nmem'}}, u'name': u'CreateVM'}, u'requestId': u'EdwReques tId.c9de162a-d606-43a1-9257-b7367c9da5de', u'timestamp': u'2017-10-24T09:43:17Z'}, u'version': u'1.0', u'context': {u'AudioPlayer': {u'p layerActivity': u'IDLE'}, u'System': {u'device': {u'supportedInterfaces': {}}, u'application': {u'applicationId': u'amzn1.ask.skill.b2a1 91bb-7ee2-4fa7-aa7b-456d4bd2ee35'}, u'user': {u'userId': u'amzn1.ask.account.BFHTSNCIVD2HA563BEPLRW5TSCESQEZXCIULPPB2ULOZBIJRCPM5Z5NWOWH 3HWNOZRTY4WT3FZFVGWWPKRSKC4ZNDSB2EYB45TYQ3RNY67CZPGF4GBMV6CL57C5MJVPIQPH25DQWGXGALDBCBRHMG5IA3Y26UHI7MHPIV3665ZU5OESS3UBADD7MDYQBWJZFB3X HJS6IM2Y5UTQ'}}}}
You can not test you skills inside of the Amazon developer portal because these will not return a Dialogstate for your dialog. If you want to test your skill i suggest you go to echosim.io or get an echo dot to experiment with.
If you don't want to test with echosim.io or a real echo device and you have your skill code inside of AWS Lambda you can always test your code there with the test command.
Example:
{
"session": {
"new": true,
"sessionId": "SessionId.******************0ed735901",
"application": {
"applicationId": "amzn1.ask.skill.e96d9***********3ee1b958e6ca"
},
"attributes": {},
"user": {
"userId": "amzn1.ask.account.AGMQGVEZFE355BBMXYBQGFN7TRN5E5CSGUU5Y3AUNEBT3DOZ7IOQ3K7G3RGIOI7BEJVLVR4CWSARSTMAF5RNA4QW************DURTSESLYMYDVIQLWA2LF6PHG3KB3UEOLZWYBBWLRKCFFMG7JFP7TNKCS2RQ4KOGPIMOT2PGQT3S2HAOBNJSAA
}
},
"request": {
"type": "IntentRequest",
"dialogState": "IN_PROGRESS",
"requestId": "EdwRequestId.5b2a45f7-e4bb-44cd-ba9f-1cfe138d577f",
"intent": {
"name": "SearchIntent",
"slots": {
"AnswerTime": {
"name": "AnswerTime",
"value": "Nope"
},
"FirstTime": {
"name": "FirstTime",
"value": "02:00"
},
"SecondTime": {
"name": "SecondTime"
},
"Date": {
"name": "Date",
"value": "2017-10-20"
},
"Name": {
"name": "Name",
"value": "Liam De Lee"
}
}
},
"locale": "en-US",
"timestamp": "2017-10-19T13:29:17Z"
},
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.e96d95e0-8cbd-41d2-a280-3ee1b958e6ca"
},
"user": {
"userId": "amzn1.ask.account.AGMQGVEZFE355BBMXYBQGFN7TRN5E5CSGUU5Y3AUNEBT3DOZ7IOQ3K7G3RGIOI7BEJVLVR4CWSARSTMAF5RNA4QW************DURTSESLYMYDVIQLWA2LF6PHG3KB3UEOLZWYBBWLRKCFFMG7JFP7TNKCS2RQ4KOGPIMOT2PGQT3S2HAOBNJSAA"
},
"device": {
"supportedInterfaces": {}
}
}
},
"version": "1.0"
}
Note: Service Simulator does not currently support testing audio
player directives, dialog model, customer permissions and customer
account linking.
Amazon developer portal.