package com.amazonaws.serverless.proxy.spring.echoapp; import com.amazonaws.serverless.proxy.spring.echoapp.model.SingleValueModel; import com.amazonaws.serverless.proxy.spring.echoapp.model.ValidatedUserModel; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.ServletContextAware; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation; @RestController @EnableWebMvc @RequestMapping("/context") public class ContextResource implements ServletContextAware { public static final String COOKIE_DOMAIN = "mydomain.com"; public static final String COOKIE_NAME = "CustomCookie"; public static final String COOKIE_VALUE = "CookieValue"; public static final String EXCEPTION_REASON = "There was a conflict"; private ServletContext context; @RequestMapping(path = "/echo", method= RequestMethod.GET) public ResponseEntity<String> getContext() { return new ResponseEntity<String>(this.context.getServerInfo(), HttpStatus.OK); } @RequestMapping(path = "/user", method=RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<ValidatedUserModel> createUser(@Valid @RequestBody ValidatedUserModel newUser, BindingResult results) { if (results.hasErrors()) { return new ResponseEntity<ValidatedUserModel>(newUser, HttpStatus.BAD_REQUEST); } return new ResponseEntity<ValidatedUserModel>(newUser, HttpStatus.OK); } @RequestMapping(path = "/cookie", method=RequestMethod.GET) public SingleValueModel setCookie(ServletRequest request, ServletResponse response) { setCookie(request, response, COOKIE_NAME, COOKIE_VALUE, true, false, true, null, false); return new SingleValueModel(); } @RequestMapping(path = "/exception", method=RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public SingleValueModel handleException() { throw new SpringConflictException(); } public static void setCookie(ServletRequest request, ServletResponse response, String name, String value, boolean set, boolean global, boolean bSecureCookie, Integer maxAge, boolean httpOnly) { Cookie ck = new Cookie(name, value); HttpServletRequest httpRequest = (HttpServletRequest) request; if (httpOnly) { ck.setHttpOnly(true); } if (set) { if (maxAge != null) { ck.setMaxAge(maxAge.intValue()); } else { ck.setMaxAge(-1); } } else { ck.setMaxAge(0); } ck.setPath("/"); // for local and fngn envs., we should not set cookie as a secure cookie if (bSecureCookie) { ck.setSecure(true); } ck.setDomain(COOKIE_DOMAIN); ((HttpServletResponse) response).addCookie(ck); } @Override public void setServletContext(ServletContext servletContext) { context = servletContext; } @ControllerAdvice class ExceptionHandlerAdvice { @ExceptionHandler({ SpringConflictException.class }) @ResponseBody ResponseEntity<SingleValueModel> handle(Exception exception) { SingleValueModel body = new SingleValueModel(); body.setValue(resolveAnnotatedExceptionReason(exception)); HttpStatus responseStatus = resolveAnnotatedResponseStatus(exception); return new ResponseEntity<>(body, responseStatus); } HttpStatus resolveAnnotatedResponseStatus(Exception exception) { ResponseStatus annotation = findMergedAnnotation(exception.getClass(), ResponseStatus.class); if (annotation != null) { return annotation.value(); } return HttpStatus.INTERNAL_SERVER_ERROR; } String resolveAnnotatedExceptionReason(Exception exception) { ResponseStatus annotation = findMergedAnnotation(exception.getClass(), ResponseStatus.class); if (annotation != null && !"".equals(annotation.reason())) { return annotation.reason(); } return exception.getLocalizedMessage(); } } @ResponseStatus(value=HttpStatus.CONFLICT, reason= EXCEPTION_REASON) public class SpringConflictException extends RuntimeException { } }