How to mount all but some URLs to a single page? - wicket

I'm working on a single page application and want to mount arbitrary URLs my home page (Index.class), e.g.
/index
/home
/foo
/somethingelse
...
But some URLs should not be handled, to deliver static assets and access the REST api e.g.:
/api
/images
/css
So my question is, how to configure Wicket to route all but some special URLs to a single page. I guess I have to implement a custom RequestMapper and delegeate to the default one. Maybe something like this:
public class WicketApplication extends WebApplication {
#Override
public Class<? extends WebPage> getHomePage() {
return Index.class;
}
#Override
public void init() {
mount(new IRequestMapper() {
// routing logic goes here
});
mountPage("/${page}", Index.class);
}
}
additionally, I defined ${page} as an URL parameter to inject some config dynamically.

I don't have the entire picture of your code, but you could simply mount Wicket application to a different path (ex: /myapp) and use another one for static/REST resources.

Related

TYPO3: Howto show records from a folder outside the page tree

In my TYPO3 installaion I have configured two websites in two separate page trees. Now I would like to show a record of a custom extension in website A but the record is stored in the page tree of website B.
This is the showAction in my controller:
public function showAction(\Vendor\Extension\Domain\Model\Event $event)
{
$this->view->assign('event', $event);
}
In the repository I disabled the storage page restriction with the following lines of code:
class EventRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
public function initializeObject()
{
$querySettings = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings::class);
$querySettings->setRespectStoragePage(false);
$this->setDefaultQuerySettings($querySettings);
}
}
Showing a record on website A which is stored in the page tree of website A, works without any problems. But as soon as I try to load a record of the page tree of website B on website A it fails.
So is it possible to show records which are stored outside of the page tree?
Your EventRepository has nothing to do with the parameter resolving for the showAction(). This should just work when given an uid of an event.
I suspect you also use routeEnhancers and maybe you chose 'eval: uniqueInSite' for the slug configuration? - in that case try without routeEnhancers to verify.

How can I change the name of the node AEM creates when a component is first dropped on the page?

I’m trying to figure out if it’s possible to customize the name of the node AEM creates when I first drop a component on the page.
The cq:Component node where my component is defined is named “knowledge-center-question” and when I drop it, AEM creates a node named “knowledge_center_que” in the page’s node tree using its default naming logic. I would prefer for the node name to be “question” when it is dropped (but I’d rather not rename the component itself).
It seems like this kind of thing must be possible given how customizable everything is in AEM, but I’m struggling to find an answer.
Take a look at :nameHints, which can be send as POST arguments to the SlingPostServlet: https://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.html#algorithm-for-node-name-creation
You need to write a custom Sling post processor. Sling post processor is called after a component dropped in the page. Example code :
#Component(service = SlingPostProcessor.class, immediate = true, name = "com.aem.CustomPostProcessor")
public class CustomPostProcessor implements SlingPostProcessor {
#Override
public void process(SlingHttpServletRequest request, List<Modification> modifications) throws Exception {
if (accepts(request)) {
final Resource resource = request.getResourceResolver().getResource(request.getResource().getPath());
// Your logic
modifications.add(Modification.onCreated(resource.getPath()));
}
}
protected boolean accepts(SlingHttpServletRequest request) {
return "/my/resource/type".equals(request.getResource().getResourceType());
}
}

Force ASP .Net Web API to block HTTP requests with Error (403)

I would like to configure my project to not allow http requests with the following restrictions:
It must be a global restriction for all APIs (via web.config, script in the installer, etc.)
It must be hard coded(not pressing "Require SSL" on the APP in the IIS)
No "redirect"- just return error (403)
my ideal option would be to configure "Require SSL" by a script which runs in the installer.
This can be accomplished by writing a simple ActionFilter that inspects the request and responds when the scheme is not set to ssl. A very minimal implementation may look something like:
public class RequireHttpsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
}
}
}
To make this apply everywhere, you'll likely want to register it as a global filter in the WebAPI configuration when your application is bootstrapping. That would look something like:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new RequireHttpsAttribute());
// ... More configuration ...
}
}
If you search the web a bit, you can find many examples of similar filters with more robust logic that may better meet your needs.

MVC 6 Attribute Routing using the new "[controller]/[action]" Tokens and Areas

OK, I know the easiest way to use Attribute Routing in MVC 6 is:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
And here is the controller code using the new Tokens (without Areas):
[Route("[controller]/[action]")]
public class HomeController : Controller
{
}
And here is the controller code using the new Tokens (with Areas):
[Area("MyArea")]
[Route("[controller]/[action]")]
public class HomeController : Controller
{
}
Questions:
Is this how MS wants you to code your controllers using Areas and Tokens?
Or is there a cleaner way?
Could they have somehow created an [area] Token?
Lastly, I know I can play this game, but isn't the 1st convention-based approach - app.UseMvc() - the simplest?
public void Configure(IApplicationBuilder app)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
});
}
Microsoft gives you two options, each with own pros and cons. You should decide which one is better based on your context/needs.
Convention based routing
Pros:
It is simpler, instead of defining everything on an per-action level you just decide once and for all how your urls will looks like .
Perfect when your urls exactly match controller/action names.
If you want to change and url you need change the name of class/method.
Perfect for projects with clean and predictable url structure.
Perfect for quickly prototyping a new project.
Slightly easier for developers -> by knowing an url you know in which controller/action lies the functionality
Cons:
You loose little bit of control
Attribute-based routing
Pros:
Gives you total control over how the url looks like, for example for SEO purposes.
If you want to change an url you do not need to change the name of class/method.
Perfect when your urls do not match controller and action names or you want to hand-craft them (i.e customer wants that).
Perfect for maintaining backward compatibility, when you have an legacy project and want to have compatible url structure.
Cons:
Requires little bit more work, as you need to define the routes in your code. Please note that adding an attribute to a class/method is a matter of seconds.
How to decide which one to use:
If you have/expect to have very few routes.MapRoute() calls -> use convention routing as its simpler
If you have/expect to have lots of routes.MapRoute() calls -> use attribute routing

Retrieve same data from application and REST

Using Zend Framework, if I want to receive the same data from my application and via REST, would this be handled by the same action contoller i.e.
articlesController extends Zend_Controller_Action
{
listAction()
{
// Service layer get data
// REST request return results in JSON
// Normal request return view
}
}
Or should this be in separate controllers?
articlesController extends Zend_Controller_Action
{
listAction()
{
// Service layer get data
// Returns view
}
}
articlesController extends Zend_Rest_Controller
{
getAction()
{
// Service layer get data
// Returns view
}
}
Hope that makes sense
Thanks guys
In a default MVC Zend Framework setup the Controller and Action names are linked to the path. The router examines the path and then dispatches to the appropriate controller and action.
With that in mind it doesn't really matter how you set this up. It only depends how you like to structure your paths.
If you have certain information in your path with the additional parameters you could combine everything within one action. Your first param could be "api" for REST request or if your additional params are in the URI path you have a regular request but if the params are in a GET array you have a API REST request. That would all work for your first example and I guess you already thinking that way.
For me it would be more appropriate to have an API path, though. With that you will have a API controller and the corresponding actions. In your second example this would mean your API controller looks more like this
apiController extends Zend_Rest_Controller {
articlesAction() {
// your REST data here
}
}
// URI path: /api/articles
Note that you cannot have two controllers with the same name.