How to get response statusCode from filterRequest function Ballerina - http

I am new in Ballerina, I try to print a log that containe some request informations like path .. and statusCode which is a response information.
How can I do that safely ?
I want to make the both logs in same log
public function filterRequest(http:Caller caller, http:Request request, http:FilterContext context) returns boolean {
log:printInfo(remoteAdress + " " + request.method + " " + request.rawPath);
return true;
}
public function filterResponse(http:Response response, http:FilterContext context) returns boolean {
log:printInfo(response.statusCode.toString());
return true;
}

Currently only service name and resource name can be accessed from http:FilterContext by default. However, any request properties such as rawPath and method can be added to the http:FilterContext attributes map. This can be retrieved in the http:ResponseFilter
public type RequestFilter object {
*http:RequestFilter;
public function filterRequest(http:Caller caller, http:Request request,
http:FilterContext context) returns boolean {
map<any> attributesMap = context.attributes;
attributesMap["rawPath"] = request.rawPath;
attributesMap["method"] = request.method;
return true ;
}
};
public type ResponseFilter object {
*http:ResponseFilter;
public function filterResponse(http:Response response,
http:FilterContext context) returns boolean {
log:printInfo(context.getServiceName());
log:printInfo(context.getResourceName());
log:printInfo(context.attributes["rawPath"].toString());
log:printInfo(context.attributes["method"].toString());
return true ;
}
};

Related

Test method issue

I tried this code:
//CONTROLLER
#GetMapping(path = "/validateToken/{id}")
public ResponseEntity<Boolean> validateToken(#PathVariable String id) {
try {
boolean bool=webSSOService.validateToken(id);
return new ResponseEntity<Boolean>(bool, HttpStatus.OK);
} catch (Exception e) {
LOGGER.error(Message.ERROR_OCCURRED+Thread.currentThread().getStackTrace()[1].getMethodName()+": "+ e.getMessage());
if (LOGGER.isDebugEnabled()) {
e.printStackTrace();
}
return new ResponseEntity<Boolean>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
//SERVICE
#Override
public boolean validateToken(String id) throws JsonProcessingException {
Map<String,Object> parameters=new HashMap<>();
parameters.put("id",id);
String uri="/SSOServiceToken/validateToken/{id}";
HttpMethod httpMethod=HttpMethod.GET;
boolean bool=executeFilteredRequest(parameters,uri,Boolean.class,httpMethod);
return bool;
}
private <T> T executeFilteredRequest(Map<String,Object> parameters, String uri, Class<T> type, HttpMethod httpMethod) throws JsonProcessingException {
RestTemplate restTemplate = restTemplateBuilder.build();
HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
headers.setContentType(MediaType.APPLICATION_JSON);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://localhost:8180" + uri);
String jsonBody="";
if (httpMethod == HttpMethod.POST){
ObjectMapper objectMapper=new ObjectMapper();
jsonBody=objectMapper.writeValueAsString(parameters);
}else{
parameters.forEach( (key, value) -> builder.queryParam(key,value));
}
HttpEntity<?> entity = new HttpEntity<>(jsonBody,headers);
ResponseEntity<T> response = restTemplate.exchange(builder.toUriString(),
httpMethod,
entity,
type);
return response.getBody();
}
Then I have to test validateToken:
#Test
public void validateTokenIsOk() throws Exception {
mockMvc.perform(MockMvcRequestBuilders
.get("/validateToken/{id}","c8r1p15dv5lr0on")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
}
The method validateToken takes an id Token, which its flag is false, in input, and then its output should become true.
Now, I always obtain a 200 status code and false as response, in every case, when I try to perform the test with Intellij. Furthermore, I obtain a message: "Token '%7Bid%7D' not found on database".
But if I try to test with Postman, result is true as expected.
What's wrong with my code? Why is the id"%7Bid%7D", instead of "c8r1p15dv5lr0on"? How is "%7Bid%7D" generated?
I hope I was clear in my question.
Thank you very much!
Problem solved. In my service:
#Override
public boolean validateToken(String id) throws JsonProcessingException {
Map<String,Object> parameters=new HashMap<>();
String uri="/SSOServiceToken/validateToken"+id;
.
.
.
That "%7Bid%7D" string was an encoded one of "{id}" in uri variable. So, in order to avoid that spurious string, I need to concatenate my uri with id variable.

How can I get dynamic response when using Spring Cloud Contract?

org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/weather'
}
response {
status 200
body([
"weather": value(regex("(SUNNY|WINDY|CLOUDY|RAINY)"))
])
}
I know Groovy DSL is able to generate a random value, Like the code above.
But the Groovy DSL just generate a static stub, and it will always return the same response as I requested.
How can I get a random weather without re-generate the stubs in this case?
You can't, that's because WireMock stub needs a concrete value on the response side. The only thing you could do is to reference the request from the response and then the request can have random input. In general, your tests shouldn't depend on random response.
I know is an old question but I found a workaround solution to achieve that using dynamic values from the given request, you can set a custom headers using $regex then use as output response.
Groovy
request {
method 'GET'
url """/v1/persons/${anyUuid()}"""
headers {
contentType('application/json')
header 'Authorization' : 'Mocked Return Data'
header 'nameMocked' : $(regex('[a-zA-Z0-9]{5, 30}'))
header 'dateMocked' : $(regex('(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[012])/([0-9]{4})'))
header 'typeMocked' : $(regex('CONSUMER|COMMERCIAL'))
}
}
response {
status 200
body(
"""
{
"name": "${fromRequest().header('nameMocked')}",
"date": "${fromRequest().header('dateMocked')}",
"type": "${fromRequest().header('typeMocked')}",
}
"""
)
headers {
contentType('application/json')
}
}
BaseClass
class PersonDto {
private UUID id;
private String name;
private LocalDate date;
private PersonType type;
}
#Slf4j
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = JacksonAutoConfiguration.class)
public abstract class BaseTest {
#Autowired
private ObjectMapper objectMapper;
#Before
public void setup() throws Exception {
YourController yourController = spy(new YourController());
//normal business mocks
doAnswer((Answer<ResponseEntity>) invocation -> {
HttpServletRequest currentRequest = getCurrentRequest();
Map<String, String> map = Collections.list(currentRequest.getHeaderNames()).stream()
.filter(n -> n.endsWith("Mocked"))
.collect(Collectors.toMap(k -> k.replaceFirst("Mocked", ""), currentRequest::getHeader));
return ResponseEntity.ok(objectMapper.convertValue(map, PersonDto.class)); //Convert map to dto
}).when(YourController).getPerson(matches("([a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8})"), eq("Mocked Return Data")); //This should match your request
RestAssuredMockMvc.standaloneSetup(yourController);
}
private HttpServletRequest getCurrentRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
Assert.state(requestAttributes != null, "Could not find current request via RequestContextHolder");
Assert.isInstanceOf(ServletRequestAttributes.class, requestAttributes);
HttpServletRequest servletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
Assert.state(servletRequest != null, "Could not find current HttpServletRequest");
return servletRequest;
}
}
Consumer example
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
#AutoConfigureStubRunner(workOffline = true, ids = "groupId:artifactId:+:stubs:8083")
#DirtiesContext
public class ConsumerContractAT {
#Test
public void callApiGetShouldReturnDynamicMockedData() {
Response response = RestAssured.given()
.header(HttpHeaders.AUTHORIZATION, "Mocked Return Data")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header("nameMocked", "Test")
.header("typeMocked", "CONSUMER")
.header("dobMocked", DateTimeFormatter.ofPattern("dd/MM/yyyy").format(LocalDate.of(2019, 10, 10)))
.when()
.get("/v1/persons/{tokeId}", UUID.randomUUID())
.then()
.statusCode(200)
.extract().response();
assertThat(response.jsonPath().getString("typeMocked")).isEqualTo("CONSUMER");
assertThat(response.jsonPath().getString("name")).isEqualTo("Test");
assertThat(response.jsonPath().getString("dob")).isEqualTo("10/10/2019");
response = RestAssured.given()
.header(HttpHeaders.AUTHORIZATION, "Mocked Return Data")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.header("nameMocked", "Test 2")
.header("typeMocked", "COMMERCIAL")
.header("dobMocked", DateTimeFormatter.ofPattern("dd/MM/yyyy").format(LocalDate.now()))
.when()
.get("/v1/persons/{tokeId}", UUID.randomUUID())
.then()
.statusCode(200)
.extract().response();
assertThat(response.jsonPath().getString("typeMocked")).isEqualTo("COMMERCIAL");
assertThat(response.jsonPath().getString("name")).isEqualTo("Test 2");
assertThat(response.jsonPath().getString("dob")).isEqualTo(DateTimeFormatter.ofPattern("dd/MM/yyyy").format(LocalDate.now()));
}
}

How to send http request parameters using Jersey client

I use the following rest client implementation of jersey to consume a rest service.I am able to do it successfully.Additionally now I need to send request parameters which will be consumed as part of HttpServletRequest on the producer side.
Consumer side Jersey client code
private ClientResponse getWebClientResponse(String RESOURCE_PATH, String methodType, Object requestObj) {
WebResource webResource;
ClientResponse response = null;
try {
String environmentHost = EnvironmentUtil.resolveEnvironmentHost();
Client client = prepareClient();
String RWP_BASE_URI = environmentHost + "/workflow/rest";
webResource = client.resource(RWP_BASE_URI);
WebResource path = webResource.path(RESOURCE_PATH);
if (GET.equals(methodType)) {
response = path.type(javax.ws.rs.core.MediaType.APPLICATION_JSON).get(
ClientResponse.class);
} else if (POST.equalsIgnoreCase(methodType)) {
response = path.type(javax.ws.rs.core.MediaType.APPLICATION_JSON).post(ClientResponse.class, requestObj);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return response;
}
Producer side
#Context
public void setContext(SecurityContext context) {
this.context = context;
}
public HttpServletRequest getRequest() {
return request;
}
#Context
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public String getSessionUserPID(final HttpServletRequest request,
final SecurityContext context) {
if (request.getSession(false) == null) {
final String exceptionMessage = "getSessionUserPID() failed, session NOT FOUND for this request";
final Response response = Response.status(ExceptionStatus.UNAUTHORIZED.getNumber())
.entity(exceptionMessage).build();
LOG.error(exceptionMessage);
throw new WebApplicationException(response);
}
if (context.getUserPrincipal() == null) {
final String exceptionMessage = "getSessionUserPID() failed, user principal NOT FOUND";
final Response response = Response.status(ExceptionStatus.UNAUTHORIZED.getNumber())
.entity(exceptionMessage).build();
LOG.error(exceptionMessage);
throw new WebApplicationException(response);
}
final String userPID = context.getUserPrincipal().getName();
if (userPID == null || userPID.isEmpty()) {
final String exceptionMessage = "getSessionUserPID() failed, user principal name cannot be null or empty";
final Response response = Response.status(ExceptionStatus.UNAUTHORIZED.getNumber())
.entity(exceptionMessage).build();
LOG.error(exceptionMessage);
throw new WebApplicationException(response);
}
return userPID;
}
The main intention here is currently I get user information from weblogic security context but for a particular scenario I need to pass this part of rest service request and obtain it from HttpServletRequest object.How can I obtain this from httpservletrequest
You can use QueryParam or PathParam in GET method and FormParam in the POST method for sending request parameter to the server.

Call a WCF Data service boolean method

I'm trying to receive an answer from a WCF method from the client. When I try to execute void methods, they are working fine. For example:
Uri u = new Uri(string.Format(LogIn.ctx.BaseUri + "/CreateRole?name='{0}'",
TextBox1.Text), UriKind.RelativeOrAbsolute);
LogIn.ctx.Execute(u, "GET");
Now I want to call a method which returns a boolean, and this value will be used. Here's the method I want to call and receive its returned value:
[WebGet]
public bool Controler(string role, string user)
{
if (Roles.IsUserInRole(user, role))
{
return true;
}
else
{
return false;
}
}
Instead of LogIn.ctx.Execute(u, "GET"), try this:
IEnumerable<bool> result = LogIn.ctx.Execute<bool>(u);
bool answer = result.Single();

BookMark Redirection using AOP-Spring interceptor

I was trying to write an interceptor using spring AOP.The interceptor will find if a request URL is a bookmark,if so will redirect to the authentication page.
Code Snippet:
public Object invoke(MethodInvocation invocation) throws Throwable {
logger.entering(this.getClass().getSimpleName(), "invoke", invocation);
Object result = null;
try {
// Logic to exclude the beans as per the list in the configuration.
boolean excluded = false;
for (String excludebean : excludedBeans) {
if (excludebean != null && excludebean.equalsIgnoreCase(invocation.getThis().getClass().getSimpleName())) {
excluded = true;
break;
}
}
// If the Target Method is "toString", then set EXCLUDE to TRUE and process the request
if(excluded == false && invocation.getMethod().getName().equalsIgnoreCase("toString"))
{
excluded = true;
}
// if user session object is available, then process the request or
// else forward to the configured view.
if (excluded || getSessionHolder().getUserVO() != null) {
result = invocation.proceed();
}
else {
logger.logp(Level.INFO, this.getClass().getSimpleName(),
"invoke(MethodInvocation)", "User Object is "+ getSessionHolder().getUserVO()
+ ". So redirecting user to home page");
result = new ModelAndView("redirect:/security/authenticate.do");
}
}
catch (Throwable ex) {
throw ex;
}
logger.exiting(this.getClass().getSimpleName(), "invoke");
return result;
}
When I debug the control comes inside the else block as expected but after I return the result,control goes to the handle method for the bookmarked URl ratehr than the handler for the redirect view.
Pls help me on this..Thanks in advance.
Why Do you need AOP for the interceptor. You can redirect easily using Regular interceptor.
public class RedirectInterceptor extends HandlerInterceptorAdapter{
private String redirectMapping;
public void setRedirectMapping(String redirectMapping) {
this.redirectMapping = **maintenanceMapping**;
}
//before the actual handler will be executed
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
if (somethingHappened){
response.sendRedirect(redirectMapping);
return false;
} else
return true;
}
}

Resources