in akka-http, how to match a path segment with an optional end slash? - akka-http

this path directive of akka http matches /hello
lazy val userRoutes: Route = cors() {
path(Segment) { p => ... }
how can I match both /hello and /hello/ (optional end slash)?
After reading the doc https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/path-directives/index.html#pathdirectives
I've tried as follows, but it does not compile:
lazy val userRoutes: Route = cors() {
rawPathPrefix(Slash ~ Segment ~ pathEndOrSingleSlash) { p => ... }

Akka-Http provides path directives using which you can solve the following.
val route =
pathPrefix("hello") {
pathEndOrSingleSlash {
complete("/hello")
}
}
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/path-directives/pathEndOrSingleSlash.html

Related

Write a dynamic Terraform block for a load balancer listener rule

I'm new to dynamic blocks and am having some trouble writing rules to listeners on a load balancer that was created using for_each.
Below are the resources I created:
resource "aws_lb_listener" "app_listener_forward" {
for_each = toset(var.app_listener_ports)
load_balancer_arn = aws_lb.app_alb.arn
port = each.value
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
certificate_arn = var.ssl_cert
default_action {
type = "forward"
forward {
dynamic "target_group" {
for_each = aws_lb_target_group.app_tg
content {
arn = target_group.value["arn"]
}
}
stickiness {
enabled = true
duration = 86400
}
}
}
}
resource "aws_lb_listener_rule" "app_https_listener_rule" {
for_each = toset(var.app_listener_ports)
listener_arn = aws_lb_listener.app_listener_forward[each.value].arn
action {
type = "forward"
forward {
dynamic "target_group" {
for_each = aws_lb_target_group.app_tg
content {
arn = target_group.value["arn"]
}
}
}
}
dynamic "condition" {
for_each = var.images
path_pattern {
content {
values = condition.value["paths"]
}
}
}
}
resource "aws_lb_target_group" "app_tg" {
for_each = var.images
name = each.key
port = each.value.port
protocol = "HTTP"
target_type = "ip"
vpc_id = aws_vpc.app_vpc.id
health_check {
interval = 130
timeout = 120
healthy_threshold = 10
unhealthy_threshold = 10
}
stickiness {
type = "lb_cookie"
cookie_duration = 86400
}
}
Below are how the variables are defined:
variable "images" {
type = map(object({
app_port = number
paths = set(string)
}))
{
"app-one" = {
app_port = 3000
paths = [
"/appOne",
"/appOne/*"
]
}
"app-two" = {
app_port = 4000
paths = [
"/appTwo",
"/appTwo/*"
]
}
}
variable "app_listener_ports" {
type = list(string)
default = [
80, 443, 22, 7999, 8999
]
}
Upon executing, I am getting an error dealing with the path_pattern being unexpected:
Error: Unsupported block type
│
│ on alb.tf line 78, in resource "aws_lb_listener_rule" "app_https_listener_rule":
│ 78: path_pattern {
│
│ Blocks of type "path_pattern" are not expected here.
I've tried a few ways to get this dynamic block but am having some difficulty. Any advice would be appreciated.
Thank you!
Try it like this:
dynamic "condition" {
for_each = var.images
content {
path_pattern {
values = condition.value.paths
}
}
}
And change the type of paths from set(string) to list(string).
This is also completely acceptable:
dynamic "condition" {
for_each = var.images
content {
path_pattern {
values = condition.value["paths"]
}
}
}
However, in my opinion here it's better to not use a dynamic block for the condition to maintain readability and maintenance.
condition {
path_pattern {
values = [
"/appOne",
"/appOne/*" ## can also use variables if you prefer !!
]
}
}
I have already answered your original post related to the problem which you had after fixing the dynamic syntax.
Post URL: Error when creating dynamic terraform rule for alb listener rule

Is it possible call a javascript function inside karate-config.js file using karate.callSingle method?

reqres.feature
Feature: Reqres api test cases
Background: base url
Given url base_url
* def validateResponse = read('classpath:helpers/common_assertions.js')
Scenario: list single user get request
Given path single_user_path
When method get
Then status 200
* validateResponse()
common_assertion.js
function common_assertions() {
var contentType = karate.get("responseHeaders['Content-Type'][0]");
if (contentType !== 'application/json; charset=utf-8') {
karate.fail('content type is not json');
}
var responseType = karate.get('responseType');
if (responseType !== 'json') {
karate.fail('response type is not json');
}
var responseTime = karate.get('responseTime');
if (responseTime > 5000) {
karate.fail('response is too slow');
}
}
karate-config.js
function fn() {
var env = karate.env; // get system property 'karate.env'
karate.log('karate.env system property was:', env);
if (!env) {
env = 'dev';
}
var config = {
base_url: 'https://reqres.in/api',
single_user_path: '/users/2'
};
if (env == 'dev') {
// customize
// e.g. config.foo = 'bar';
} else if (env == 'e2e') {
// customize
}
return config;
}
I would like to use common_assertions.js file in karate-config.js file rather than using in the background section so that i can reuse * validateResponse() method across all feature files. Is there a way?Please help

Cloudflare worker redirections

Lets say that I have a website asdf.com, and I would like to write a worker that will do a lot of redirections (more than 30). For example www.asdf.com/app -> app-asdf.com, www.asdf.com/dashboard -> dashboard-asdf.com.
I tried with following, but it doesn't work:
async function handleEvent(event) {
const url = new URL(event.request.url)
// Redirects
const redirects = {
'bitgravity': 'tata-communications',
'highwinds': 'stackpath',
'maxcdn': 'stackpath',
'netdna': 'stackpath',
'level3': 'centurylink',
'/blog/feed/': '/blog/feed.xml',
'/blogdef/': '/social/blog/',
'/geodef/': '/social/geo/',
'/guidedef/': '/social/guides/',
'/blog/akamai-down/': '/blog/'
}
let target = null
for (const source in redirects) {
if (url.pathname.includes(source)) {
if(target == null){
target = new URL(url.href)
}
target = new URL(target.href.replace(source, redirects[source]))
}
}
if (target != null){
return Response.redirect(target, 301)
}
}
At the end of your function:
if (target != null){
return Response.redirect(target, 301)
}
}
If target is null -- meaning no redirects matched -- then you are not returning any value. This will produce an exception (error 1101). When running in preview, the JS console will show the error: "Uncaught (in response) TypeError: Failed to execute function: parameter 1 is not of type 'Response'."
You probably want to change the code to:
if (target != null){
return Response.redirect(target, 301)
}
return fetch(event.request)
}
Of course, your worker also needs this at the top (but I assume you just left it out for brevity):
addEventListener("fetch", event => {
return event.respondWith(handleEvent(event))
})

Example of URL builder in Ktor

I'm using Ktor client to make calls to an API and I didn't find any examples of how to construct a URL with query parameters.
I wanted something like this:
protocol = HTTPS,
host = api.server.com,
path = get/items,
queryParams = List(
Pair("since", "2020-07-17"),
)
I can't find any examples of how to use URL builder for this.
If you want to specify each of this element (protocol, host, path and params) separately you can use a HttpClient.request method to construct your url. Inside this method you have access to HttpRequestBuilder and then you can configure url with usage of UrlBuilder
client.request<Response> {
url {
protocol = URLProtocol.HTTPS
host = "api.server.com"
path("get", "items")
parameters.append("since", "2020-07-17")
}
}
Response type is your response, you can specify there whatever you need
It would also be helpful if someone wants to add a base URL to all their requests :
HttpClient(Android) {
expectSuccess = false
//config Client Serialization
install(JsonFeature) {
serializer = KotlinxSerializer(json)
}
//config client logging
install(Logging) {
level = LogLevel.BODY
}
//Config timeout
install(HttpTimeout) {
requestTimeoutMillis = 30 * 1000L
connectTimeoutMillis = 10 * 1000L
}
//Config Base Url
defaultRequest {
url {
protocol =URLProtocol.HTTPS
host = baseUrl
}
}
}
val json = kotlinx.serialization.json.Json {
ignoreUnknownKeys = true
isLenient = true
encodeDefaults = false
}

Wrong queryString when building navigation plan in aurelia-router

We're using aurelia-open-id-connect in our project and after successful login the redirect is removing the querystring from the url. I've debugged my way through the aurelia-router and I think I found something. Should'nt the queryString in redirectInstruction be used there?
export const buildRedirectPlan = (instruction: NavigationInstruction) => {
const config = instruction.config;
const router = instruction.router;
return router
._createNavigationInstruction(config.redirect)
.then(redirectInstruction => {
const params: Record<string, any> = {};
const originalInstructionParams = instruction.params;
const redirectInstructionParams = redirectInstruction.params;
for (let key in redirectInstructionParams) {
// If the param on the redirect points to another param, e.g. { route: first/:this, redirect: second/:this }
let val = redirectInstructionParams[key];
if (typeof val === 'string' && val[0] === ':') {
val = val.slice(1);
// And if that param is found on the original instruction then use it
if (val in originalInstructionParams) {
params[key] = originalInstructionParams[val];
}
} else {
params[key] = redirectInstructionParams[key];
}
}
let redirectLocation = router.generate(redirectInstruction.config, params, instruction.options);
// Special handling for child routes
for (let key in originalInstructionParams) {
redirectLocation = redirectLocation.replace(`:${key}`, originalInstructionParams[key]);
}
let queryString = instruction.queryString;
// use redirectInstruction.queryString instead?
if (queryString) {
redirectLocation += '?' + queryString;
}
return Promise.resolve(new Redirect(redirectLocation));
});
};