You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Steve Eynon <st...@alienfactory.co.uk> on 2012/08/29 12:27:59 UTC

How to return HTTP 404 for in-exact URL requests

A topic that crops up time and time again is that of the elusive HTTP
404 in T5 apps.

When running a public website, for SEO reasons, it is desirable for
in-exact urls to return a HTTP 404 rather than returning a 'best fit'
page.For the same reasons, it is undesirable for malformed urls to
return an HTTP 500. So in T5.3.4, I finally got round to converting
all those URL requests to HTTP 404s.

The approach taken is to generate a 'MangledUrlException' at poignant
points and have an ExceptionHandler catch this specific exception to
return a HTTP 404.The code changes I use to throw a
'MangledUrlException' are outlined below:

My method of catching and identifying the MangledUrlException (as it's
often wrapped deep inside a T5 exception) may not be suitable for all,
so I've left that part out.



Use Case 1 : Illegal Url "http://localhost/spa%20ce"
This usually gives a java.lang.IllegalArgumentException:
 - Input string 'spa ce' is not valid; the character ' ' at position 4
is not valid.

To your module add:

  @Advise(serviceInterface=ContextPathEncoder.class) @Traditional
  public static void adviseContextPathEncoder(MethodAdviceReceiver
receiver, @Autobuild AdviseContextPathEncoder advice) throws
SecurityException, NoSuchMethodException {
    Method method = ContextPathEncoder.class.getMethod("decodePath",
String.class);
    receiver.adviseMethod(method, advice);
  }

  public class AdviseContextPathEncoder implements MethodAdvice {
    @Override
    public void advise(MethodInvocation invocation) {
      try {
        invocation.proceed();
      } catch (IllegalArgumentException e) {
        throw new MangledUrlException();
      }
    }
  }



Use Case 2 : Illegal Url "http://localhost/index.wotever"
This usually gives an org.apache.tapestry5.ioc.util.UnknownValueException
 - Component Index does not contain embedded component 'wotever'.

  @Advise(serviceInterface=ComponentEventRequestHandler.class)
  public static void
adviseComponentEventRequestHandler(MethodAdviceReceiver receiver,
@Autobuild AdviseComponentEventRequestHandler advice) throws
SecurityException, NoSuchMethodException {
    Method method =
ComponentEventRequestHandler.class.getMethod("handle",
ComponentEventRequestParameters.class);
    receiver.adviseMethod(method, advice);
  }

  public class AdviseComponentEventRequestHandler implements MethodAdvice {
    private final String className;
    private final String methodName;

    public AdviseComponentEventRequestHandler() throws
SecurityException, NoSuchMethodException {
      // set these early so we're notified of any API changes
      // PageImpl isn't a service, so we can't advise it directly!
      className   = PageImpl.class.getName();
      methodName  =
PageImpl.class.getMethod("getComponentElementByNestedId",
String.class).getName();
    }

    @Override
    public void advise(MethodInvocation invocation) {
      try {
        invocation.proceed();
      } catch (UnknownValueException e) {
        if (componentIdIsMangled(e)) {
          ComponentEventRequestParameters params =
(ComponentEventRequestParameters) invocation.getParameter(0);
          throw new MangledUrlException(params.getActivePageName(),
MangledUrlMessages.componentNotFound(params.getNestedComponentId()),
e);
        }
      }
    }

    private boolean componentIdIsMangled(UnknownValueException e) {
      for (StackTraceElement stackElement : e.getStackTrace())
        if (stackElement.getClassName().equals(className) &&
stackElement.getMethodName().equals(methodName))
          return true;
      return false;
    }
  }



Use Case 3 : Unwanted context "http://localhost/index/unwanted"
This usually returns the index page.

  @Contribute(ComponentClassTransformWorker2.class)
  @Primary
  public static void
provideTransformWorkers(OrderedConfiguration<ComponentClassTransformWorker2>
configuration) {
    configuration.addInstance("ContextNotRequiredWorker",
NotRequiredWorker.class, "after:*");
  }

  /**
   * It's important that that this is added "after:*" as we need to
ensure no-one else has added onActivate() handlers.
   */
  public class NotRequiredWorker implements ComponentClassTransformWorker2 {
    @Override
    public void transform(PlasticClass plasticClass,
TransformationSupport support, MutableComponentModel model) {
      if (!model.isPage())
        return;

      // FUTURE: this does not identify mixins which implement onActivate()
      if (model.handlesEvent(EventConstants.ACTIVATE))
        return;

      support.addEventHandler(EventConstants.ACTIVATE, 0,
        "NotRequiredWorker activate event handler",
        new ComponentEventHandler() {
          @Override
          public void handleEvent(Component instance, ComponentEvent event) {
          if (event.getContext().length > 0) {
            String pageName = instance.getComponentResources().getPageName();
            throw new MangledUrlException(pageName,
MangledUrlMessages.contextNotWanted(event.getEventContext().toStrings()));
          }
        }
      });
    }
  }

--
Steve Eynon
-------------------------------
"If at first you don't succeed,
   so much for skydiving!"

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: How to return HTTP 404 for in-exact URL requests

Posted by Steve Eynon <st...@alienfactory.co.uk>.
If T5 could throw more specific exceptions, as oppose the generic ones
that it does, then it'd be a simple exception handling matter for the
user to decide what to do. (As mentioned above.)

I rose a JIRA about this last year:

Throw bespoke exceptions so they may be more easily identified by Error Handlers
https://issues.apache.org/jira/browse/TAP5-1733

Steve.



On 29 August 2012 19:20, Lance Java <la...@googlemail.com> wrote:
> It sounds like you are fixing something that really should be handled by
> tapestry. I agree that a 404 is much better than a 500 in these cases and I
> think it should be the default behavior.
>
>
>
> --
> View this message in context: http://tapestry.1045711.n5.nabble.com/How-to-return-HTTP-404-for-in-exact-URL-requests-tp5715875p5715876.html
> Sent from the Tapestry - User mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


How to return HTTP 404 for in-exact URL requests

Posted by Lance Java <la...@googlemail.com>.
It sounds like you are fixing something that really should be handled by
tapestry. I agree that a 404 is much better than a 500 in these cases and I
think it should be the default behavior.



--
View this message in context: http://tapestry.1045711.n5.nabble.com/How-to-return-HTTP-404-for-in-exact-URL-requests-tp5715875p5715876.html
Sent from the Tapestry - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org