Junit test with WireMock throws 404 not found expection - java

I had this problem since a week, I didn't found enough resources.
I have a java application which consume an external API, I want to test my application using wiremock.
When I want to send a file it's always shown 404 Not found.
I found that the issue is that wiremock not preserving the Host header value, so I have this code below, but it always doesn't work.
I tried the real API and it's working perfectly using WireMock Record & Playback feature, but I specify the -preserve-host-header option(without this it's getting 404 Not Found)
My service that I want to test (I don't have controllers):
#Service
public class Bank{
//This method is working
public String hello(String hello){
return exernalAPI.get("hello").toString(); // It's just an example
}
//This method is not working in test(404)
public void uploadFile(String inputStrum...){
//The code here is used to send the file to an external API using method post
}
}
I did a record and Playback to capture the request and the response from the real extern API,
Class test:
#AutoConfigureWireMock(port=0)
#ContextConfiguration(classes={Bank.class})
public class BankTest{
#Autowired
public Bank bank;
#Test //The test is passing
public void helloTest(){
String expected = resourse.getResource("classpath:response/helloMessage.txt").toString(); //Get the captured response
String actual = bank.hello("Jack"); //this return Hi Jack and it's working
assertEquals(expected,actual);
}
#Test //This test is not passing
public String uploadFileTest(){
InputSteam is = getInputStream();
//code to get inputStream
Resource expected= resourse.getResourse("classpath:responses/upload_response.json");
String expected = expected.toString();
is.setContent(resource.getResource("classpath:file_to_upload.zip"));
String actual = bank.uploadFile(is); // Here i have 404 not found
assertEquals(expected,actual);
}
after several searches I found that I have to preserve the Host header using something like this :
preserveHostHeader(true);

Related

Java DeleteMapping Method Not Allowed

I'm trying to create an api to delete a certain ID from the storage;
Here's my code.
API Controller:
#DeleteMapping("{cId}")
#ResponseStatus(HttpStatus.OK)
public String delete(#PathVariable String cId) {
compareService.delete(cId);
return "redirect:/compare";
}
Service:
public void delete(String cId) {
compareLogic.delete(cId);
}
Logic:
public void delete(String cId){
System.out.println("A: " + sessionModel.getCIds());
List<String> update = sessionModel.getCIds();
update.remove(new String(cId));
System.out.println("B: " + sessionModel.getCIds());
}
However when I execute the api it shows
{
success: false,
warning: false,
error: "405",
error_description: "Method Not Allowed"
}
Are there any possible reasons by just looking at the code?
Many thanks,
Just I have tired with simple code snippet , Could you please try to understand and (Try to follow my suggestion as well )
When you hit from browser side (From Address Bar), it won't work for POST/PUT/DELETE calls , it is actually working from browser, if you try to typing in address bar then it is a GET request then it will not supported to the other format
Just I have added two screenshot I have tired with Browser and PostMan
First I have tired with POSTMAN (it is working perfectly)
Second I have tired with Browser (It will throw not supported
exception )
I have tired with small code snippet just copy from your code and remove element from list
#DeleteMapping("{cId}")
public String delete(#PathVariable String cId) {
List<String> arr=new ArrayList<String>(3);
arr.add("A");
arr.add("B");
arr.add("C");
arr.remove(cId);
for (String string : arr) {
System.out.println(string);
}
return "redirect:/compare";
}
The reason for this error is sending the request with a non-supported method. 405 Status Code indicates that the server doesn't support the method or verb sent in the request.
Could you also provide the API call details like HTTP method and relative path ? recheck your API details, make sure you are using correct HTTP method.

Fortify Scan issue (XSS) Cross site scripting Reflected - method sends unvalidated data to webbrowser

I am getting the Fortify error which says that Method sends unvalidated data to a web browser which can result browser executing malicious code.
This is a java web application using spring framework.
Controller class :
public class Controller {
#Autowired
public Server server;
#Autowired
public Service xxxservice;
#RequestMapping("\path1\serverId\")
#ResponseBody
public String openFile(....) {
List<FilePath> filePath= getFilePaths(server, form.getPaths.values);
FileResultResponse response = xxxservice.openFile(server, getAbsolutePath(filePath);
String jsonOutput = getOutput(response,filePath);
return jsonOutput;
Server.java
class Server {
String serverName;
String serverDescription;
int serverId;
String serverAddress;
List<String> rootDirectories;
public void setServerName() {
this.serverName = serverName;
All the setter methods are available for the above class.
The report throws the error at getOutput method line saying that server.setName, server.setRootDirectories, etc should be validated before sending data to web browser.
The server values are set through some initialization method inside getFilePaths() method as below
public void initialization(server,root) {
this.server=server;
this.root=root;
How these server values should be validated to rectify the Fortify scan issue ?
As you are not dealing with byte arrays as in my case , probably you could try using
Jsoup.clean(filePath,Whitelist.basic());
This solved most of my issues except for the case where I need to write pdf from a byte array.

Creating input parameters and using java web service function in ASP.NET Web API

I have created a java web service that does addition function. I also have created an ASP.NET Web API which calls the java web service and displays the result. Lets say i typed in http://localhost:8080/addition/9/6 as the URL with input parameters that the java web service function should add. I get the output data as {"firstNumber":9,"secondNumber":6,"sum":15}. When i run my ASP.NET Web API, i will be redirected to http://localhost:55223/ and i will get the output data as {"firstNumber":9,"secondNumber":6,"sum":15}.
Right now, what i want to do is, when i run my ASP.NET Web API, i should be able to input parameters in the URL of the ASP.NET Web API (http://localhost:55223/addition/9/6) and instead of displaying result straight from Java web service, i want to use the function of the java web service in my API to calculate the sum of the input parameters. Does anyone have an idea on how can i go about doing that? What are the changes that i should make in my codes?
Here are my codes:
ASP.NET Web API codes
RestfulClient.cs
public class RestfulClient
{
private static HttpClient client;
private static string BASE_URL = "http://localhost:8080/";
static RestfulClient()
{
client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> addition(int firstNumber, int secondNumber)
{
try
{
var endpoint = string.Format("addition/{0}/{1}", firstNumber, secondNumber);
var response = await client.GetAsync(endpoint);
return await response.Content.ReadAsStringAsync();
}
catch (Exception e)
{
HttpContext.Current.Server.Transfer("ErrorPage.html");
}
return null;
}
}
ApiController.cs
public class ApiController : Controller
{
private RestfulClient restfulClient = new RestfulClient();
public async Task<ActionResult> Index()
{
int firstNumber = 9;
int secondNumber = 6;
var result = await restfulClient.addition(firstNumber, secondNumber);
return Content(result);
}
}
Java web service codes
AdditionController.java
#RestController
public class AdditionController {
private static final String template = " %s";
private static int getSum;
#RequestMapping("/addition/{param1}/{param2}")
#ResponseBody
public Addition addition
(#PathVariable("param1") int firstNumber,#PathVariable("param2") int secondNumber) {
return new Addition(
(String.format(template, firstNumber)), String.format(template, secondNumber));
}
}
Someone please help me thank you so much in advance.
what i want to do is, when i run my ASP.NET Web API, i should be able to input parameters in the URL of the ASP.NET Web API (http://localhost:55223/addition/9/6)
Web API uses many conventions and if you play nicely then things work pretty well. The first thing you need to do is to rename your controller like this:
public class AdditionController : ApiController
{
public async Task<IHttpActionResult> Get(int firstNumber, int secondNumber)
{
var result = await restfulClient.addition(firstNumber, secondNumber);
return Ok(result);
}
}
You will notice a few things in above code:
The controller is called AdditionController. When you type addition in the url, the routing engine will look for a controller named Addition + the word Controller.
It inherits ApiController not Controller.
It has a Get action. If you make a GET request, the API routing engine will search for an action named Get or starting with Get. Thus it will find this action.
The action is returning IHttpActionResult. See my answer here for why.
It uses the extension method named Ok to return an HTTP Status code of 200. This is to follow good restful guidelines and HTTP guidelines.
You can call the above like this:
http://localhost:55223/addition?firstNumber=1&secondNumber=6
If you want to be able to call it like this:
http://localhost:55223/addition/9/6
Then you need to make some changes to the WebApiConfig class. Add this to code before the code for DefaultApi:
config.Routes.MapHttpRoute(
name: "AdditionApi",
routeTemplate: "api/addition/{firstNumber}/{secondNumber}",
defaults: new { action = "Get", controller = "Addition" }
);
Above we are telling the routing engine: Hey routing engine, if the url contains the word api/addition followed by a variable and another variable, then use the Get method of the Addition controller*.

Restlet with many #Get in my server side

So I am new with restlet. I am creating a Android application that can communicate with a GAE server (with objectify DB)
I Did this very good tutorial to learn:
http://www.tutos-android.com/webservice-rest-android-appengine-restlet-objectify
It's working very well but do very little.
Onely 2 methods:
public interface UserControllerInterface {
#Put
void create(User user);
#Get
Container getAllUsers();
}
For my application its more complicated so I add many more methods:
public interface UserControllerInterface {
#Put
public void createUser(ObagooUser user);
#Put
public void createMessage(ObagooUser user, String message);
#Put
public void updateMessage(ObagooMessage message);
#Get
public List<ObagooUser> getAllUser();
#Get
public ObagooUser getUserById(String id);
#Get
public List<ObagooMessage> getAllMessage();
#Get
public List<ObagooMessage> getAllMessageFromSender(ObagooUser sender);
#Get
public ObagooMessage getFreeMessage(ObagooUser user);
}
Each of these mothds working server side (I tested with Junit).
Now I am coding the android part and I am having problems.
When I do a simple call to getAllMessage() I get an error:
java.lang.IllegalArgumentException: id cannot be zero
at com.google.appengine.api.datastore.KeyFactory.createKey(KeyFactory.java:44)
at com.googlecode.objectify.ObjectifyFactory.typedKeyToRawKey(ObjectifyFactory.java:269)
at com.googlecode.objectify.impl.ObjectifyImpl.find(ObjectifyImpl.java:159)
at com.googlecode.objectify.impl.ObjectifyImpl.find(ObjectifyImpl.java:183)
at com.obagoo.dao.ObagooUserDAO.getUserById(ObagooUserDAO.java:43)
at com.obagoo.controller.ObagooController.getUserById(ObagooController.java:47)
It's going in the wrong method (getUserById).
I put a break point in my getAllMessage and it's going in, but it is also going in other methods.
If I test many times, sometimes it's calling, createUser or another random method.
Do you see what I am doind wrong?
Adding the getAllMessage code:
public List<ObagooMessage> getAllMessage() {
// logger.debug("Getting all Obagoo Messages");
List<ObagooMessage> msg = new ArrayList<ObagooMessage>();
Objectify ofy = ObjectifyService.begin();
Query<ObagooMessage> q = ofy.query(ObagooMessage.class);
for (ObagooMessage u : q) {
msg.add(u);
}
return msg;
}
In the examples that I've seen, its always shown that you should separate the controller/resource handling the URI for the list resource from the single item (id/name based) resource. So you would have something like:
router.attach("/users", UsersController.class);
router.attach("/users/{id}", UserController.class
router.attach("/messages", MessagesController.class);
Notice the plural naming on the first class: UsersController, and singular naming on the the second class: UserController. The first class would handle cases where no id was being provided, such as a get of all users. Also, note when the id is provided in the URI, it can be automatically mapped into an id field on the class. So the Get method has no parameters on the method call.
As for handling a subset, then for messages from a specific user, that could be handled with query parameters. For instance when calling via a URI with /messages?sender=id, the MessagesController.class would use the following in the method handling the Get:
Form queryParams = getRequest().getResourceRef().getQueryAsForm();
String id = queryParams.getFirstValue("sender");
Hope that helps. I'm no expert, so anyone feel free to correct me.
As error says: you are creating a key with zero Id.
My gues is that your ObagoMessage Id field is long? You should make it Long. Primitive long Id values are not autogenerated, while object type Long are. See the docs.

Attaching parameters in calling Apis

I have writing Java code Using Jersey library to call Rest APIs.
For my first method to display all blogs i have written the code like
return webResource.path(ConfigurationUtil.LIST_BLOGS).header(ConfigurationUtil.AUTHENTICATION_HEADER, authentication)
.accept(MediaType.APPLICATION_XML_TYPE).get(new GenericType<List<CommunityBean>>() {
});
which lists all the blogs.. As my LIST_BLOGS string is like
public static final String LIST_BLOGS = "api/blogs.xml";
Its works fine..
Now I'm trying to write a code for a method where I want to extract only 2 blogs and not all
so my url will be like
public static final String LIST_BLOGS = "api/blogs.xml?limit=2";
As I am not able to send the parameter from the wrapper file to ConfigurationUtil file and I used the way as
public List<BlogBean> searchBlogsXml(String limit) {
final String SEARCH_BLOGS="api/blogs.xml?limit="+limit;
return webResource.path(SEARCH_BLOGS).header(ConfigurationUtil.AUTHENTICATION_HEADER, authentication)
.accept(MediaType.APPLICATION_XML_TYPE).get(new GenericType<List<BlogBean>>() {
});
}
When i used like above i am getting 406 error..
Why so how to avoid this ?
Please give suggestions..
You can attach a query param like this;
resource.queryParam("limit", 2).get(MyObject.class);

Categories