下面列出了怎么用javax.servlet.FilterChain的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void filterSendRedirect() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
final byte[] responseBody = "Hello World".getBytes("UTF-8");
FilterChain filterChain = (filterRequest, filterResponse) -> {
assertEquals("Invalid request passed", request, filterRequest);
response.setContentLength(100);
FileCopyUtils.copy(responseBody, filterResponse.getOutputStream());
((HttpServletResponse) filterResponse).sendRedirect("http://www.google.com");
};
filter.doFilter(request, response, filterChain);
assertEquals("Invalid status", 302, response.getStatus());
assertNull("Invalid ETag header", response.getHeader("ETag"));
assertEquals("Invalid Content-Length header", 100, response.getContentLength());
assertArrayEquals("Invalid content", responseBody, response.getContentAsByteArray());
assertEquals("Invalid redirect URL", "http://www.google.com", response.getRedirectedUrl());
}
/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
*
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String characterEncoding = selectEncoding(request);
if (characterEncoding != null) {
request.setCharacterEncoding(characterEncoding);
}
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
/**
* Perform the filtering that has been configured for this Filter, matching
* against the specified request property.
*
* @param property The request property on which to filter
* @param request The servlet request to be processed
* @param response The servlet response to be processed
* @param chain The filter chain
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
protected void process(String property, ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (isAllowed(property)) {
chain.doFilter(request, response);
} else {
if (response instanceof HttpServletResponse) {
if (getLogger().isDebugEnabled()) {
getLogger().debug(sm.getString("requestFilter.deny",
((HttpServletRequest) request).getRequestURI(), property));
}
((HttpServletResponse) response).sendError(denyStatus);
} else {
sendErrorWhenNotHttp(response);
}
}
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String authHeader = request.getHeader(this.tokenHeader);
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
String username = jwtTokenUtil.getUserNameFromToken(authToken);
LOGGER.info("checking username:{}", username);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
LOGGER.info("authenticated user:{}", username);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
/**
* Handles a CORS request that violates specification.
*
* @param request The {@link HttpServletRequest} object.
* @param response The {@link HttpServletResponse} object.
* @param filterChain The {@link FilterChain} object.
*/
private void handleInvalidCORS(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain filterChain) {
String origin = request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN);
String method = request.getMethod();
String accessControlRequestHeaders = request.getHeader(
REQUEST_HEADER_ACCESS_CONTROL_REQUEST_HEADERS);
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.resetBuffer();
if (log.isDebugEnabled()) {
// Debug so no need for i18n
StringBuilder message = new StringBuilder("Invalid CORS request; Origin=");
message.append(origin);
message.append(";Method=");
message.append(method);
if (accessControlRequestHeaders != null) {
message.append(";Access-Control-Request-Headers=");
message.append(accessControlRequestHeaders);
}
log.debug(message.toString());
}
}
private String sendRedirect(final String location) throws ServletException, IOException {
Filter filter = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res,
FilterChain chain) throws IOException {
res.sendRedirect(location);
}
};
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = new MockFilterChain(mock(HttpServlet.class), this.filter, filter);
filterChain.doFilter(request, response);
return response.getRedirectedUrl();
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String authHeader = request.getHeader(this.tokenHeader);
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
String username = jwtTokenUtil.getUserNameFromToken(authToken);
LOGGER.info("checking username:{}", username);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
LOGGER.info("authenticated user:{}", username);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// �ж��û��Ƿ��Ѿ���¼
Object user = httpServletRequest.getSession().getAttribute("userInfo");
if (user == null) {
// httpServletRequest.getRequestDispatcher("/view/login.jsp").forward(httpServletRequest,httpServletResponse);
httpServletResponse.sendRedirect("index.jsp");
return;
}
chain.doFilter(request, response);
}
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String encoding = getEncoding();
if (encoding != null) {
if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {
request.setCharacterEncoding(encoding);
}
if (isForceResponseEncoding()) {
response.setCharacterEncoding(encoding);
}
}
filterChain.doFilter(request, response);
}
@Test
public void forceEncodingAlwaysSetsEncoding() throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
request.setCharacterEncoding(ENCODING);
given(request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE)).willReturn(null);
given(request.getAttribute(filteredName(FILTER_NAME))).willReturn(null);
HttpServletResponse response = mock(HttpServletResponse.class);
FilterChain filterChain = mock(FilterChain.class);
CharacterEncodingFilter filter = new CharacterEncodingFilter(ENCODING, true);
filter.init(new MockFilterConfig(FILTER_NAME));
filter.doFilter(request, response, filterChain);
verify(request).setAttribute(filteredName(FILTER_NAME), Boolean.TRUE);
verify(request).removeAttribute(filteredName(FILTER_NAME));
verify(response).setCharacterEncoding(ENCODING);
verify(filterChain).doFilter(request, response);
}
@Test
public void noQueryStringAvailable() throws Exception {
filter.setIncludeQueryString(true);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = new NoOpFilterChain();
filter.doFilter(request, response, filterChain);
assertNotNull(filter.beforeRequestMessage);
assertTrue(filter.beforeRequestMessage.contains("[uri=/hotels]"));
assertNotNull(filter.afterRequestMessage);
assertTrue(filter.afterRequestMessage.contains("[uri=/hotels]"));
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String token = resolveToken(httpServletRequest);
// 对于 Token 为空的不需要去查 Redis
if (StrUtil.isNotBlank(token)) {
OnlineUserDTO onlineUserDto = null;
SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
try {
OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
onlineUserDto = onlineUserService.getOne(properties.getOnlineKey() + token);
} catch (ExpiredJwtException e) {
log.error(e.getMessage());
}
if (onlineUserDto != null && StringUtils.hasText(token)) {
Authentication authentication = tokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Token 续期
tokenProvider.checkRenewal(token);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String url = request.getRequestURI();
if (!urlSet.contains(url)) {
String token = request.getHeader(JwtUtils.AUTHORIZATION_HEADER_PREFIX);
String privateSecret = GovernanceApplication.governanceConfig.getPrivateSecret();
if (!StringUtils.isBlank(token) && JwtUtils.verifierToken(token, privateSecret)) {
AccountEntity accountEntity = JwtUtils.decodeToken(token, privateSecret);
if (accountEntity != null) {
log.info("get token from HTTP header, {} : {}", JwtUtils.AUTHORIZATION_HEADER_PREFIX, token);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(accountEntity.getUsername(), null, null);
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
filterChain.doFilter(request, response);
} else {
String newPath = url.replace("/weevent-governance", "");
RequestDispatcher requestDispatcher = request.getRequestDispatcher(newPath);
requestDispatcher.forward(request, response);
}
}
private void filterWithParameterForMethod(String methodParam, String expectedMethod)
throws IOException, ServletException {
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/hotels");
if(methodParam != null) {
request.addParameter("_method", methodParam);
}
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = new FilterChain() {
@Override
public void doFilter(ServletRequest filterRequest,
ServletResponse filterResponse) throws IOException, ServletException {
assertEquals("Invalid method", expectedMethod,
((HttpServletRequest) filterRequest).getMethod());
}
};
this.filter.doFilter(request, response, filterChain);
}
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
HttpServletRequestWrapper quoted =
new RequestQuoter((HttpServletRequest) request);
HttpServletResponse httpResponse = (HttpServletResponse) response;
String mime = inferMimeType(request);
if (mime == null) {
httpResponse.setContentType("text/plain; charset=utf-8");
} else if (mime.startsWith("text/html")) {
// HTML with unspecified encoding, we want to
// force HTML with utf-8 encoding
// This is to avoid the following security issue:
// http://openmya.hacker.jp/hasegawa/security/utf7cs.html
httpResponse.setContentType("text/html; charset=utf-8");
} else if (mime.startsWith("application/xml")) {
httpResponse.setContentType("text/xml; charset=utf-8");
}
headerMap.forEach((k, v) -> httpResponse.addHeader(k, v));
chain.doFilter(quoted, httpResponse);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: " +
"no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
try {
//优先获取请求参数中的tenantId值
String tenantId = request.getParameter(CommonConstant.TENANT_ID_PARAM);
if (StrUtil.isEmpty(tenantId)) {
tenantId = request.getHeader(SecurityConstants.TENANT_HEADER);
}
//保存租户id
if (StrUtil.isNotEmpty(tenantId)) {
TenantContextHolder.setTenant(tenantId);
}
filterChain.doFilter(request, response);
} finally {
TenantContextHolder.clear();
}
}
@Test
public void queryStringIncluded() throws Exception {
filter.setIncludeQueryString(true);
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
request.setQueryString("booking=42");
FilterChain filterChain = new NoOpFilterChain();
filter.doFilter(request, response, filterChain);
assertNotNull(filter.beforeRequestMessage);
assertTrue(filter.beforeRequestMessage.contains("[uri=/hotels?booking=42]"));
assertNotNull(filter.afterRequestMessage);
assertTrue(filter.afterRequestMessage.contains("[uri=/hotels?booking=42]"));
}
@Test
public void withBeanInitialization() throws Exception {
HttpServletRequest request = mock(HttpServletRequest.class);
given(request.getCharacterEncoding()).willReturn(null);
given(request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE)).willReturn(null);
given(request.getAttribute(filteredName(FILTER_NAME))).willReturn(null);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding(ENCODING);
filter.setBeanName(FILTER_NAME);
filter.setServletContext(new MockServletContext());
filter.doFilter(request, response, filterChain);
verify(request).setCharacterEncoding(ENCODING);
verify(request).setAttribute(filteredName(FILTER_NAME), Boolean.TRUE);
verify(request).removeAttribute(filteredName(FILTER_NAME));
verify(filterChain).doFilter(request, response);
}
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String bearerToken = resolveBearerToken(request);
if (StringUtils.isBlank(bearerToken)) {
filterChain.doFilter(request, response);
return;
}
if (authenticationIsRequired()) {
try {
authInterceptor.setAccessToken(bearerToken);
ResponseEntity<BearerTokenTO> validateResponse = ledgersUserMgmt.validate(bearerToken);
BearerTokenTO token = Optional.ofNullable(validateResponse.getBody())
.orElseThrow(() -> new RestException("Couldn't get bearer token"));
fillSecurityContext(token);
} catch (FeignException | RestException e) {
handleAuthenticationFailure(response, e);
return;
}
}
filterChain.doFilter(request, response);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: " +
"no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
@Test
public void filterFlushResponse() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
final byte[] responseBody = "Hello World".getBytes("UTF-8");
FilterChain filterChain = (filterRequest, filterResponse) -> {
assertEquals("Invalid request passed", request, filterRequest);
((HttpServletResponse) filterResponse).setStatus(HttpServletResponse.SC_OK);
FileCopyUtils.copy(responseBody, filterResponse.getOutputStream());
filterResponse.flushBuffer();
};
filter.doFilter(request, response, filterChain);
assertEquals("Invalid status", 200, response.getStatus());
assertEquals("Invalid ETag header", "\"0b10a8db164e0754105b7a99be72e3fe5\"", response.getHeader("ETag"));
assertTrue("Invalid Content-Length header", response.getContentLength() > 0);
assertArrayEquals("Invalid content", responseBody, response.getContentAsByteArray());
}
/**
* <p>Intercepts the specified request. If a valid authentication token is provided by the specified request then
* set-ups current security context with authenticated principal based on the provided token.</p>
*
* @param servletRequest an incoming request.
* @param servletResponse an outgoing response.
* @param filterChain a filter chain mapped to specified request.
* @throws IOException if an I/O error occurs in filter chain.
* @throws ServletException if an unexpected error occurs in filter chain.
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String jwt = resolveToken(httpServletRequest);
if (jwt != null && !jwt.trim().isEmpty() && this.tokenProvider.validateToken(jwt)) {
User authUser = this.tokenProvider.getAuthentication(jwt);
// Set-up the security context
try {
SecurityContext.init(authUser);
filterChain.doFilter(servletRequest, servletResponse);
} finally {
SecurityContext.release();
}
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
// 如果请求头中没有Authorization信息则直接放行
if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
// 如果请求头中有token,则进行解析,并且设置认证信息
try {
SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
} catch (TokenIsExpiredException e) {
//返回json形式的错误信息
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.getWriter().write(JSON.toJSONString(R.failed(e.getMessage())));
response.getWriter().flush();
return;
}
super.doFilterInternal(request, response, chain);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
try {
DefaultSavedRequest savedRequest = (DefaultSavedRequest)request.getSession().getAttribute(SAVED_REQUEST);
if (savedRequest != null) {
String[] clientIds = savedRequest.getParameterValues("client_id");
if (ArrayUtil.isNotEmpty(clientIds)) {
//保存租户id
TenantContextHolder.setTenant(clientIds[0]);
}
}
chain.doFilter(request, response);
} finally {
TenantContextHolder.clear();
}
}
@Test
public void filterSendError() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
final byte[] responseBody = "Hello World".getBytes("UTF-8");
FilterChain filterChain = (filterRequest, filterResponse) -> {
assertEquals("Invalid request passed", request, filterRequest);
response.setContentLength(100);
FileCopyUtils.copy(responseBody, filterResponse.getOutputStream());
((HttpServletResponse) filterResponse).sendError(HttpServletResponse.SC_FORBIDDEN);
};
filter.doFilter(request, response, filterChain);
assertEquals("Invalid status", 403, response.getStatus());
assertNull("Invalid ETag header", response.getHeader("ETag"));
assertEquals("Invalid Content-Length header", 100, response.getContentLength());
assertArrayEquals("Invalid content", responseBody, response.getContentAsByteArray());
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
String authHeader = request.getHeader(this.tokenHeader);
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
String username = jwtTokenUtil.getUserNameFromToken(authToken);
LOGGER.info("checking username:{}", username);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
LOGGER.info("authenticated user:{}", username);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new HttpServletRequestWrapper(request) {
@Override
public Principal getUserPrincipal() {
return () -> PRINCIPAL_NAME;
}
// Like Spring Security does in HttpServlet3RequestFactory..
@Override
public AsyncContext getAsyncContext() {
return super.getAsyncContext() != null ?
new AsyncContextWrapper(super.getAsyncContext()) : null;
}
}, new HttpServletResponseWrapper(response));
}
@Test
public void filterSendError() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
final byte[] responseBody = "Hello World".getBytes("UTF-8");
FilterChain filterChain = (filterRequest, filterResponse) -> {
assertEquals("Invalid request passed", request, filterRequest);
response.setContentLength(100);
FileCopyUtils.copy(responseBody, filterResponse.getOutputStream());
((HttpServletResponse) filterResponse).sendError(HttpServletResponse.SC_FORBIDDEN);
};
filter.doFilter(request, response, filterChain);
assertEquals("Invalid status", 403, response.getStatus());
assertNull("Invalid ETag header", response.getHeader("ETag"));
assertEquals("Invalid Content-Length header", 100, response.getContentLength());
assertArrayEquals("Invalid content", responseBody, response.getContentAsByteArray());
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (!StringUtils.isEmpty(request.getContentType())
&& MediaType.APPLICATION_JSON.isCompatibleWith(MediaType.valueOf(request.getContentType()))) {
chain.doFilter(new ContentCachingRequestWrapper((HttpServletRequest)request), response);
} else {
chain.doFilter(request, response);
}
}