11package io .github .wimdeblauwe .htmx .spring .boot .mvc ;
22
3- import com .fasterxml .jackson .core .JsonProcessingException ;
4- import com .fasterxml .jackson .databind .ObjectMapper ;
53import jakarta .servlet .http .HttpServletRequest ;
64import jakarta .servlet .http .HttpServletResponse ;
75import org .springframework .http .HttpHeaders ;
86import org .springframework .web .method .HandlerMethod ;
97import org .springframework .web .servlet .HandlerInterceptor ;
8+ import org .springframework .web .servlet .ModelAndView ;
109
1110import java .lang .reflect .Method ;
12- import java .util .Collection ;
13- import java .util .HashMap ;
14- import java .util .stream .Collectors ;
1511
1612/**
1713 * HandlerInterceptor that adds htmx specific headers to the response.
1814 */
1915public class HtmxHandlerInterceptor implements HandlerInterceptor {
2016
21- private final ObjectMapper objectMapper ;
22- private final HtmxHandlerMethodAnnotationHandler handlerMethodAnnotationHandler ;
17+ private final HtmxHandlerMethodHandler htmxHandlerMethodHandler ;
2318
24- public HtmxHandlerInterceptor (ObjectMapper objectMapper , HtmxHandlerMethodAnnotationHandler handlerMethodAnnotationHandler ) {
25- this .objectMapper = objectMapper ;
26- this .handlerMethodAnnotationHandler = handlerMethodAnnotationHandler ;
19+ public HtmxHandlerInterceptor (HtmxHandlerMethodHandler htmxHandlerMethodHandler ) {
20+ this .htmxHandlerMethodHandler = htmxHandlerMethodHandler ;
2721 }
2822
2923 @ Override
30- public void afterCompletion (HttpServletRequest request , HttpServletResponse response , Object handler , Exception ex ) throws Exception {
31-
32- HtmxResponse htmxResponse = RequestContextUtils .getHtmxResponse (request );
33- if (htmxResponse != null ) {
34- addHxTriggerHeaders (response , HtmxResponseHeader .HX_TRIGGER , htmxResponse .getTriggers ());
35- addHxTriggerHeaders (response , HtmxResponseHeader .HX_TRIGGER_AFTER_SETTLE , htmxResponse .getTriggersAfterSettle ());
36- addHxTriggerHeaders (response , HtmxResponseHeader .HX_TRIGGER_AFTER_SWAP , htmxResponse .getTriggersAfterSwap ());
37-
38- if (htmxResponse .getReplaceUrl () != null ) {
39- response .setHeader (HtmxResponseHeader .HX_REPLACE_URL .getValue (), RequestContextUtils .createUrl (request , htmxResponse .getReplaceUrl (), htmxResponse .isContextRelative ()));
40- }
41- if (htmxResponse .getPushUrl () != null ) {
42- response .setHeader (HtmxResponseHeader .HX_PUSH_URL .getValue (), RequestContextUtils .createUrl (request , htmxResponse .getPushUrl (), htmxResponse .isContextRelative ()));
43- }
44- if (htmxResponse .getRetarget () != null ) {
45- response .setHeader (HtmxResponseHeader .HX_RETARGET .getValue (), htmxResponse .getRetarget ());
46- }
47- if (htmxResponse .getReselect () != null ) {
48- response .setHeader (HtmxResponseHeader .HX_RESELECT .getValue (), htmxResponse .getReselect ());
49- }
50- if (htmxResponse .getReswap () != null ) {
51- response .setHeader (HtmxResponseHeader .HX_RESWAP .getValue (), htmxResponse .getReswap ().toHeaderValue ());
52- }
53- }
24+ public void postHandle (HttpServletRequest request , HttpServletResponse response , Object handler , ModelAndView modelAndView ) throws Exception {
25+ htmxHandlerMethodHandler .handleMethodArgument (request , response );
5426 }
5527
5628 @ Override
5729 public boolean preHandle (HttpServletRequest request ,
5830 HttpServletResponse response ,
5931 Object handler ) {
6032
61- if ( handler instanceof HandlerMethod ) {
62- Method method = (( HandlerMethod ) handler ). getMethod ();
63- setVary ( request , response );
64- handlerMethodAnnotationHandler . handleMethod ( method , request , response );
33+ setVary ( request , response );
34+
35+ if ( handler instanceof HandlerMethod handlerMethod ) {
36+ htmxHandlerMethodHandler . handleMethodAnnotations ( handlerMethod . getMethod () , request , response );
6537 }
6638
6739 return true ;
@@ -73,35 +45,4 @@ private void setVary(HttpServletRequest request, HttpServletResponse response) {
7345 }
7446 }
7547
76- private void setHeaderJsonValue (HttpServletResponse response , HtmxResponseHeader header , Object value ) {
77- try {
78- response .setHeader (header .getValue (), objectMapper .writeValueAsString (value ));
79- } catch (JsonProcessingException e ) {
80- throw new IllegalArgumentException ("Unable to set header " + header .getValue () + " to " + value , e );
81- }
82- }
83-
84- private void addHxTriggerHeaders (HttpServletResponse response , HtmxResponseHeader headerName , Collection <HtmxTrigger > triggers ) {
85- if (triggers .isEmpty ()) {
86- return ;
87- }
88-
89- // separate event names by commas if no additional details are available
90- if (triggers .stream ().allMatch (t -> t .getEventDetail () == null )) {
91- String value = triggers .stream ()
92- .map (HtmxTrigger ::getEventName )
93- .collect (Collectors .joining ("," ));
94-
95- response .setHeader (headerName .getValue (), value );
96- return ;
97- }
98-
99- // multiple events with or without details
100- var triggerMap = new HashMap <String , Object >();
101- for (HtmxTrigger trigger : triggers ) {
102- triggerMap .put (trigger .getEventName (), trigger .getEventDetail ());
103- }
104- setHeaderJsonValue (response , headerName , triggerMap );
105- }
106-
10748}
0 commit comments