Locale in Routing, Default Language also without Parameter - annotations

I want to define the page language via url on a Symfony2 installation. My routing works via annotation inside the controller.
routing.yml
_index:
resource: "#MyMainBundle/Controller/SiteController.php"
type: annotation
siteController.php
/**
* #Route( "/{_locale}/{site}", name="_site_site", defaults={"_locale" = "en"}, requirements={"site" = "about|cities|download|blog", "_locale" = "en|de|fr|es"} )
*/
This works quiet well, but waht I want, is that the following url call the same action.
http://example.com/download
http://example.com/en/download
http://example.com/de/download
Without the languge-parameter, the page should switch back to the default language, but this is something I can handle inside my action.
I found this Answer, but could not get it to work at all.
Symfony2 default locale in routing

Just add another #Route annotation that does not include the locale.
/**
* #Route("/{_locale}/{site}/")
* #Route("/{site}/")
*/

This also works within annotations.yaml
frontend_controllers:
resource: ../../src/Controller/Frontend
type: annotation
prefix:
- /
- /{_locale}
defaults:
_locale: 'en'

Another simular solution for Symfony 5 that worked for me :
# config/routes/annotations.yaml
controllers:
resource: '../../src/Controller/'
type: annotation
prefix:
fr: ''
en: '/en'
Symfony documentation : https://symfony.com/doc/current/routing.html#localized-routes-i18n

Also if you have an api prefix you can use next config
controllers:
resource: ../../src/Controller/
type: annotation
prefix:
- api
- api/{_locale}
defaults:
_locale: en

Related

Request-based Sticky Session configuration with Spring Cloud LoadBalancer

I have the following configuration for request-based sticky session using Spring Cloud LoadBalancer
spring:
cloud:
discovery.client.simple.instances:
say-hello:
- instanceId: say-hello1
uri: http://localhost:8080
- instanceId: say-hello2
uri: http://localhost:8081
loadbalancer:
configurations: request-based-sticky-session
sticky-session:
add-service-instance-cookie: true
server.port:9090
the following call:
$ http :9090/hi 'Cookie:sc-lb-instance-id=say-hello1'
should go only to the say-hello1 instance based on the Request-based Sticky Session for LoadBalancer but instead is using round robin load balancing.
What do I miss here?
Here is the source code to try it: https://github.com/altfatterz/client-side-loadbalancing
There are 2 things to consider here:
In the sample, the cookie has to be passed on to the actual load-balanced request, for example like so:
#GetMapping("/hi")
public String hi(#RequestParam(value = "name", defaultValue = "Mary") String name) {
logger.info("Accessing /hi endpoint");
HttpHeaders headers = new HttpHeaders();
headers.set("Cookie", "sc-lb-instance-id=say-hello1");
HttpEntity entity = new HttpEntity(headers);
ResponseEntity<String> greeting = restTemplate.exchange("http://say-hello/greeting", HttpMethod.GET, entity, String.class, new HashMap<>());
return greeting + " " + name;
}
This feature is only supported for WebClient-backed load-balancing. It was not properly documented. I have documented it here.
I have also created a GitHub issue for adding the non-reactive implementation, however, the decision to implement it will be dependant on larger community interest.

NewRelic::Rack middleware not exposing Sinatra::Base settings

I have a modular Sinatra app, where I use
run Rack::URLMap
to add various services, where each service is a Sinatra::Base
I've added a middleware in one of the services that uses the settings method. It seems that the NewRelic rack middlewares are not exposing this method.
class MyService < Sinatra::Base
configure do
set :optional_auth, [
{ method: :get, path: ''},
{ method: :get, path: '/:id'},
{ method: :get, path: '/:id/attachments'},
{ method: :get, path: '/:id/comments'}
]
mime_type :json, 'application/json'
use Rack::PostBodyContentTypeParser
use MyMiddleware
end
get '/' ....
Locally, things work fine, however, when deployed, it seems that MyMiddleware is being added after NewRelic::Rack, so when the middleware is invoked, the #app is no longer MyService, it's NewRelic::Rack without the exposed settings method.
Has anyone else experienced this? I'm running the application with bundle exec puma
I was able to work around this by updating my middleware
def initialize app, &block
#app = app
#block = block
end
def call env
#block.call(env)
do_something(env[:my_middleware_option])
...
#app.call(env)
end
And initializing my middleware with
use MyMiddleware do |env|
env[:my_middleware_option] = "any data type"
end

Deny access to one particular subpath for spring cloud gateway route

We're using Spring Cloud Gateway in front of our backend services. We have a route similar to the following:
routes:
- id: foobar-service
uri: lb://foobar-service
predicates:
- Path=/foobar/**
filters:
- StripPrefix=1
We want to deny access to one particular subpath (e.g. /foobar/baz/**) but leave the rest open. Is it possible to do this using the YAML syntax? Perhaps we need to implement the routes using the Fluent API instead?
routes:
- id: foobar-baz-service
uri: no://op
predicates:
- Path=/foobar/baz/**
filters:
- SetStatus=403
- id: foobar-service
uri: lb://foobar-service
predicates:
- Path=/foobar/**
filters:
- StripPrefix=1
Sharing my experience with the API implementation with a single route.
#Bean
public RouteLocator routes( final RouteLocatorBuilder locatorBuilder ) {
RouteLocatorBuilder.Builder builder = locatorBuilder.routes();
builder.route(p -> p //
.path(getAllowedPaths()) //
.and() //
.not(n -> n.path(getRestrictedPaths()) //
.filters(f -> f //
//filters
.uri(uri)));
return builder.build();
}

Symfony 4 argument has no type-hint, you should configure its value explicitly

Symfony 4.2.3
Recently upgraded from version 3.4 to 4.2.3 and got my project working, but
when setting autoconfigure in services.yaml to true, I will receive this error message:
Cannot autowire service "App\EventListener\RedirectToLocaleActiveListener": argument "$localeActive" of method "__construct()" has no type-hint, you should configure its value explicitly.
My services.yaml
parameters:
locale: de
locale_active: de
app_locales: de|en
uploads_directory_name: uploads
uploads_profile_directory_name: profiles
uploads_directory: '%kernel.root_dir%/../public/%uploads_directory_name%'
profile_directory: '%kernel.root_dir%/../public/%uploads_directory_name%/%uploads_profile_directory_name%'
google_recaptcha_site_key: '%env(GOOGLE_RECAPTCHA_SITE_KEY)%'
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
App\Controller\:
resource: ../src/Controller
tags:
- controller.service_arguments
locales:
class: App\Util\Locales
arguments:
- '%locale_active%'
- '%app_locales%'
- '#session'
app.locale:
class: App\EventListener\LocaleListener
tags:
- {name: kernel.event_subscriber}
app.redirect_to_locale_active:
class: App\EventListener\RedirectToLocaleActiveListener
arguments:
- '#router'
- '%locale_active%'
tags:
- {name: kernel.event_subscriber}
My RedirectToLocaleActiveListener.php
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Class RedirectToLocaleActiveListener
* When a user enters to the homepage without the parameter locale,
* the subscriber redirects the user to the main locale.
*
* #package App\EventListener
*/
class RedirectToLocaleActiveListener implements EventSubscriberInterface
{
/**
* #var UrlGeneratorInterface
*/
private $urlGenerator;
/**
* #var string
*/
private $localeActive;
/**
* #param UrlGeneratorInterface $urlGenerator
* #param $localeActive
*/
public function __construct(UrlGeneratorInterface $urlGenerator, $localeActive)
{
$this->urlGenerator = $urlGenerator;
$this->localeActive = $localeActive;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
];
}
/**
* #param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if ('/' == $request->getPathInfo()) {
$route = $this->urlGenerator->generate('app_index', ['_locale' => $this->localeActive]);
$response = new RedirectResponse($route);
$event->setResponse($response);
}
}
}
What I've tried:
adding 'string' to $localActive in __construct of RedirectToLocaleActiveListener
Result:
Cannot autowire service "App\EventListener\RedirectToLocaleActiveListener": argument "$localeActive" of method "__construct()" is type-hinted "string", you should configure its value explicitly.
arguments of scalar type cannot be auto-wired. You need to wire them manually.
You can try wiring the argument explicitly in the service definition:
App\EventListener\RedirectToLocaleActiveListener
arguments:
$urlGenerator: '#router'
$localeActive: '%locale_active%'
tags:
- {name: kernel.event_subscriber}
Documentation:
https://symfony.com/doc/current/service_container.html#manually-wiring-arguments
Or you can make use of the local service binding feature to bind a parameter to a scalar argument:
services:
_defaults:
bind:
$localeActive: '%locale_active%'
Documentation:
https://symfony.com/blog/new-in-symfony-3-4-local-service-binding
If your service name is not equal to fqcn, such as:
app.ext.telegram_bot_api:
class: 'App\Ext\TelegramBot\Bot'
and somewhere your using automatic services resolution like this:
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Document,Migrations,Tests,Kernel.php}'
your should create alias between your service name and fqcn like that:
'App\Ext\TelegramBot\Bot': '#app.ext.telegram_bot_api'
so your automatic services resolution should know about your service extra configuration.

Zuul Routing on Root Path

I want to config zuul to route request to root / to a home page. I tried:
root:
path: /
url: http://hostname/home/index.jsp
and
root:
path: /**
url: http://hostname/home/index.jsp
But neither of them works. I just got a 404 NOT FOUND. I think the path match config should be similar to those with contexts, such as /service/**, but it's not.
This is what I have done to make this work.
Within Zuul -> controller:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String handleRequest() {
return "forward:/ux/";
}
Zuul Properties:
zuul:
addProxyHeaders: true
routes:
example-ux:
path: /ux/**
stripPrefix: false
Within example-ux Service properties:
server:
servlet-path: /*
context-path: /ux
This configuration also solves the problem of static resources resolution. i.e. /static/css static/js etc...