Context routing for two different apps - ibm-cloud

I deploy two different apps to CF and I want to be able to use the context path routing for those two apps
e.g.
lets say I've two apps that deployed and I was able to consume it with the following URL.
1. app1.domain.com
2. app2.domain.com
Now I want somehow to use the context path routing of CF
to be able to use this apps like following
1. something.domain.com/app1
2. something.domain.com/app2
My question are:
I missing the "something", what should I put in the apps manifest to be able to use it like above ?
How should I define the routes in the mainfest.yml file?
what should I put in the path?
Example will be very helpful
https://www.cloudfoundry.org/context-path-routing/

Lucky that I recently prepared a blog post and a tutorial on context path routing. Here is a sample manifest.yml taken from the tutorial that shows two apps with different routes on the same domain:
# This manifest deploys two applications.
#
# Both use the same host and domain name as defined
# by their respective route(s) property. The first app
# uses the root path, the second the "sub" and
# "lower" paths.
applications:
# The Python app starts here
- name: yourname-myapp
memory: 256M
command: python myapp.py
routes:
- route: yourname-myapp.mybluemix.net
path: ./top/
# The Node.js app starts here
- name: yourname-myapp-node
routes:
- route: yourname-myapp.mybluemix.net/lower
- route: yourname-myapp.mybluemix.net/sub
path: ./lower/
You can even define multiple routes for a single app, all in a single manifest file. The routes property is the place for the routing information. Note that the path points to the source code for the app (if done this way) and that you need a recent version of cf CLI to deploy it. See the tutorial for more information and additional links.

You can also find a good example in the map route documentation per below
https://docs.cloudfoundry.org/devguide/deploy-apps/routes-domains.html#map-route

Related

Differences in designing a serverless function vs. regular server

I am wondering what approach in designing serverless functions to take, while taking designing a regular server as a point of reference.
With a traditional server, one would focus on defining collections and then CRUD operations one can run on each of them (HTTP verbs such as GET or POST).
For example, you would have a collection of users, and you can get all records via app.get('/users', ...), get specific one via app.get('/users/{id}', ...) or create one via app.post('/users', ...).
How differently would you approach designing a serverless function? Specifically:
Is there a sense in differentiating between HTTP operations or would you just go with POST? I find it useful to have them defined on the client side, to decide if I want to retry in case of an error (if the operation is idempotent, it will be safe to retry etc.), but it does not seem to matter in the back-end.
Naming. I assume you would use something like getAllUsers() when with a regular server you would define collection of users and then just use GET to specify what you want to do with it.
Size of functions: if you need to do a number of things in the back-end in one step. Would you define a number of small functions, such as lookupUser(), endTrialForUser() (fired if user we got from lookupUser() has been on trial longer than 7 days) etc. and then run them one after another from the client (deciding if trial should be ended on the client - seems quite unsafe), or would you just create a getUser() and then handle all the logic there?
Routing. In serverless functions, we can't really do anything like .../users/${id}/accountData. How would you go around fetching nested data? Would you just return a complete JSON every time?
I have been looking for some comprehensive articles on the matter but no luck. Any suggestions?
This is a very broad question that you've asked. Let me try answering it point by point.
Firstly, the approach that you're talking about here is the Serverless API project approach. You can clone their sample project to get a better understanding of how you can build REST apis for performing CRUD operations. Start by installing the SAM cli and then run the following commands.
$ sam init
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Cloning from https://github.com/aws/aws-sam-cli-app-templates
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Multi-step workflow
3 - Serverless API
4 - Scheduled task
5 - Standalone function
6 - Data processing
7 - Infrastructure event management
8 - Machine Learning
Template: 3
Which runtime would you like to use?
1 - dotnetcore3.1
2 - nodejs14.x
3 - nodejs12.x
4 - python3.9
5 - python3.8
Runtime: 2
Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.
Based on your selections, the only dependency manager available is npm.
We will proceed copying the template using npm.
Project name [sam-app]: sample-app
-----------------------
Generating application:
-----------------------
Name: sample-app
Runtime: nodejs14.x
Architectures: x86_64
Dependency Manager: npm
Application Template: quick-start-web
Output Directory: .
Next steps can be found in the README file at ./sample-app/README.md
Commands you can use next
=========================
[*] Create pipeline: cd sample-app && sam pipeline init --bootstrap
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
Comings to your questions point wise:
Yes, you should differentiate your HTTP operations with their suitable HTTP verbs. This can be configured at the API Gateway and can be checked for in the Lambda code. Check the source code of handlers & the template.yml file from the project you've just cloned with SAM.
// src/handlers/get-by-id.js
if (event.httpMethod !== 'GET') {
throw new Error(`getMethod only accepts GET method, you tried: ${event.httpMethod}`);
}
# template.yml
Events:
Api:
Type: Api
Properties:
Path: /{id}
Method: GET
The naming is totally up to the developer. You can follow the same approach that you're following with your regular server project.
You can define the handler with name getAllUsers or users and then set the path of that resource to GET /users in the AWS API Gateway. You can choose the HTTP verbs of your desire. Check this tutorial out for better understanding.
Again this up to you. You can create a single Lambda that handles all that logic or create individual Lambdas that are triggered one after another by the client based on the response from the previous API. I would say, create a single Lambda and just return the cumulative response to reduce the number of requests. But again, this totally depends on the UI integration. If your screens demand separate API calls, then please, by all means create individual lambdas.
This is not true. We can have dynamic routes specified in the API Gateway.
You can easily set wildcards in your routes by using {variableName} while setting the routes in API Gateway.
GET /users/{userId}
The userId will then be available at your disposal in the lambda function via event.pathParameters.
GET /users/{userId}?a=x
Similarly, you could even pass query strings and access them via event.queryStringParameters in code. Have a look at working with routes.
Tutorial I would recommend for you:
Tutorial: Build a CRUD API with Lambda and DynamoDB

How to configure localized URLs in kubernetes nginx ingress controller API object

I have a cluster in Azure AKS with 1 node.
On that cluster I have two back-end services.
Each back-end service is a web app.
I have a domain mydomain.com.
Each app will need to be configured with its own path rule in the ingress object.
Web app 1s (let's call this one the homepage app) target URL needs to be either of the following:
US version of the site: mydomain.com
Swedish version of the site: mydomain.com/se/sv-sv/hem
Any other location/language version of the site: mydomain.com/xx/yy-xx/abcdefgh
Web app 2s (let's call this one the whitepony app) target URL needs to be either of the following:
US version of the site: mydomain.com/us/en-us/whitepony
Swedish version of the site: mydomain.com/se/sv-sv/whitepony
Any other location/language version of the site: mydomain.com/xx/yy-xx/whitepony
(The whitepony apps target path segment is called whitepony regardless of location/language)
Now to my question.
How can I configure these rules in an ingress API object?
Can I use prefixes in the path rules?
Or do I need to use regular expressions?
And what about the special case of the US version of the homepage app, where I'm not using any prefixes/extra URL segments?
Can I use conditions in the ingress object?
Or how would you configure the ingress resource object to meet all the above requirements?
Note that I know and have successfully configured multiple back-end services using path rules in an ingress object.
But without prefixes or extra URL segments.
I won't give you fully working example on how to specify rules in ingress resource to meet your requirements, I would rather like to share with you some hints:
Yes, you will need regular expressions to achieve it, and here is the example of doing it directly with NGINX directives based on example of wordpress multi-language site.
You don't need to define these re-write rules with annotations, you can use for that pure NGINX config style, by supplying appropriate inline NGINX config file inside ConfigMap, here is the example on how to achieve this.
I hope this will help you

Spring Web: Mapping URL to a standalone Spring app

I have two standalone Spring Boot/Web web app .jars, A and B, both made by third-parties, with their own URL mappings which I do not know about in advance.
I would like to create a setup where "localhost:8080/A" maps (passes through) to A's "/" mapping. Similarly, "localhost:8080/B" should pass through to B's "/" mapping.
Additional mappings, which again I don't necessarily know about in advance, should also pass through respectively - so "localhost:8080/A/items" should pass through to A's "/items", etc.
I do not have the source code for A or B, only .jar files.
For security, A and B should have separate scopes with no knowledge of each other or ability to interact with each other. The whole setup should behave as if A and B were separate "inner" servers within my "outer" localhost server.
Can this be achieved via a Spring Boot/Web wrapper or gateway app, or some other way?
You could use spring boot with Zuul as a third app, running on 8080, which has routes setup for A and B similar to what you described.
zuul:
routes:
app-A:
path: /A/**
url: http://localhost:8081/
app-B:
path: /B/**
url: http://localhost:8082/
That configuration (application.yml) of your third app would point "A" traffic to port 8081 and "B" traffic to port 8082.
This is quick and dirty, but should get you started.
Alternatively, you could use spring cloud gateway, to get a similar type of setup with the additional ability to do sockets/reactive.

phalcon include modules in rest

I am trying to include a module in Phalcon Micro Application. Is that possible?
I have a structure like this
common/
components/
...
modules/
system
components
...
controllers
...
rest
components
...
controllers
...
www
controllers
...
www/
index.php -> Loads /Phalcon/Mvc/Application($di);
api/
index.php -> Loads /Phalcon/Mvc/Micro($di);
The www registers the modules from config
I want the api to register the rest module from config and include the controllers and the components of that module. Is that possible?
Thanks,
Gasim
Obviously all is possible !
If you want to keep your structure with application+micro I think the best way is to create 3 configs.
A first config that is common with both of api and www
A second one which is loaded only by your www with its one router
A thirds one which is loaded only by your api with its one microrouter and which redefines the different paths to the rest module.
If you want just to use a multi module application with a single config file, then I can advice you to use the domain recognition in your router thanks to the setHostName() method.
Then in your config file you define an api hostname and a www hostname that you use everytime. You may also put them in global constant for more convenience.
// an api get route
$router->add("/getsomething",...)
->via("GET")
->setHostname(MyApp::HOSTNAME_API);
// an api post route
$router->add("/postsomething",...)
->via("POST")
->setHostname(MyApp::HOSTNAME_API);
// a www route
$router->add("/",...)->setHostname(MyApp::HOSTNAME_WEB);
I am trying to include a module in Phalcon Micro Application. Is that possible?
Yes, no problem!
I want the api to register the rest module from config and include the controllers and the components of that module. Is that possible?
Looking at your description and structure I understand it as you would like to separate the configuration of the www module and api module. This will work fine and you only need to include your api configuration in www/index.php (since that is where you start your application and where all your requests will go). Good luck!

CherryPy : Accessing Global config

I'm working on a CherryPy application based on what I found on that BitBucket repository.
As in this example, there is two config files, server.cfg (aka "global") and app.cfg.
Both config files are loaded in the serve.py file :
# Update the global settings for the HTTP server and engine
cherrypy.config.update(os.path.join(self.conf_path, "server.cfg"))
# ...
# Our application
from webapp.app import Twiseless
webapp = Twiseless()
# Let's mount the application so that CherryPy can serve it
app = cherrypy.tree.mount(webapp, '/', os.path.join(self.conf_path, "app.cfg"))
Now, I'd like to add the Database configuration.
My first thought was to add it in the server.cfg (is this the best place? or should it be located in app.cfg ?).
But if I add the Database configuration in the server.cfg, I don't know how to access it.
Using :
cherrypy.request.app.config['Database']
Works only if the [Database] parameter is in the app.cfg.
I tried to print cherrypy.request.app.config, and it shows me only the values defined in app.cfg, nothing in server.cfg.
So I have two related question :
Is it best to put the database connection in the server.cfg or app.cfg file
How to access server.cfg configuration (aka global) in my code
Thanks for your help! :)
Put it in the app config. A good question to help you decide where to put such things is, "if I mounted an unrelated blog app at /blogs on the same server, would I want it to share that config?" If so, put it in server config. If not, put it in app config.
Note also that the global config isn't sectioned, so you can't stick a [Database] section in there anyway. Only the app config allows sections. If you wanted to stick database settings in the global config anyway, you'd have to consider config entry names like "database_port" instead. You would then access it directly by that name: cherrypy.config.get("database_port").