Testing ASP.NET Web API Multipart Form Data File upload - unit-testing

I am trying to use N-UNIT to test my web API application but I am unable to find a proper way to test my file upload method. Which would be the best approach to test the method?
Web API Controller:
[AcceptVerbs("post")]
public async Task<HttpResponseMessage> Validate()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
return Request.CreateErrorResponse(HttpStatusCode.UnsupportedMediaType,"please submit a valid request");
}
var provider = new MultipartMemoryStreamProvider(); // this loads the file into memory for later on processing
try
{
await Request.Content.ReadAsMultipartAsync(provider);
var resp = new HttpResponseMessage(HttpStatusCode.OK);
foreach (var item in provider.Contents)
{
if (item.Headers.ContentDisposition.FileName != null)
{
Stream stream = item.ReadAsStreamAsync().Result;
// do some stuff and return response
resp.Content = new StringContent(result, Encoding.UTF8, "application/xml"); //text/plain "application/xml"
return resp;
}
}
return resp;
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}

Based on your above comment, following is an example:
HttpClient client = new HttpClient();
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
formDataContent.Add(new StringContent("Hello World!"),name: "greeting");
StreamContent file1 = new StreamContent(File.OpenRead(#"C:\Images\Image1.jpeg"));
file1.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
file1.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
file1.Headers.ContentDisposition.FileName = "Image1.jpeg";
formDataContent.Add(file1);
StreamContent file2 = new StreamContent(File.OpenRead(#"C:\Images\Image2.jpeg"));
file2.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
file2.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
file2.Headers.ContentDisposition.FileName = "Image1.jpeg";
formDataContent.Add(file2);
HttpResponseMessage response = client.PostAsync("http://loclhost:9095/api/fileuploads", formDataContent).Result;
The request over the wire would like:
POST http://localhost:9095/api/fileuploads HTTP/1.1
Content-Type: multipart/form-data; boundary="34d56c28-919b-42ab-8462-076b400bd03f"
Host: localhost:9095
Content-Length: 486
Expect: 100-continue
Connection: Keep-Alive
--34d56c28-919b-42ab-8462-076b400bd03f
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=greeting
Hello World!
--34d56c28-919b-42ab-8462-076b400bd03f
Content-Type: image/jpeg
Content-Disposition: form-data; filename=Image1.jpeg
----Your Image here-------
--34d56c28-919b-42ab-8462-076b400bd03f
Content-Type: image/jpeg
Content-Disposition: form-data; filename=Image2.jpeg
----Your Image here-------
--34d56c28-919b-42ab-8462-076b400bd03f--

After spending a bit of time looking into WebClient I was able to come up with this:
try
{
var imageFile = Path.Combine("dir", "fileName");
WebClient webClient = new WebClient();
byte[] rawResponse = webClient.UploadFile(string.Format("{0}/api/values/", "http://localhost:12345/"), imageFile);
Console.WriteLine("Sever Response: {0}", System.Text.Encoding.ASCII.GetString(rawResponse)); // for debugging purposes
Console.WriteLine("File Upload was successful");
}
catch (WebException wexc)
{
Console.WriteLine("Failed with an exception of " + wexc.Message);
// anything other than 200 will trigger the WebException
}

Related

Can't call method with PUT or POST

I can request an API method via http://requestmaker.com/ using GET, but when I use POST or PUT it returns...
HTTP/1.1 403 Forbidden
Here is the method...
[HttpPost]
[Route("api/sales")]
public object Put([FromBody] Sale sale)
{
sale.DateTime = DateTime.Now;
paymentRepository.Insert(sale);
paymentRepository.Save();
return Ok(new { id = sale.SaleId });
}
Any ideas?
Request headers are...
POST /admin/api/sales HTTP/1.1 Host: hello.com Accept: /
Content-Type: text/html Content-Length: 17
Request data...
TourId=3&UserId=1
It has to do with how your Controller is routing the requests. You seem to have defined something like this
Defaults To GET:
public async Task<IHttpActionResult> MethodName(){
return this.Ok()
}
or
[HttpGet]
public async Task<IHttpActionResult> MethodName(){
return this.Ok()
}
There should be some attributes that you can define above the function:
For POST:
[HttpPost]
public async Task<IHttpActionResult> MethodNamePost(){
return this.Ok()
}
For PUT:
[HttpPut]
public async Task<IHttpActionResult> MethodNamePut(){
return this.Ok()
}
Like Win said:
[HttpPut]
[Route("api/sales")]
public object Put([FromBody] Sale sale)
{
sale.DateTime = DateTime.Now;
paymentRepository.Insert(sale);
paymentRepository.Save();
return new { id = sale.SaleId };
}
I would change the return to this.Ok(new {id = sale.SaleId}); though.
Your Request headers are wrong it should be like
{
"UserId":"1",
"TourID":"3",
}
REASON:application/json
Oh silly me, it was looking for an anti-forgery token. I thought I'd commented the filter out, but I'd done it for MVC and not Web Api. Oops.
I also needed to set the content type to application/json and set the data as { "TourId":"3", "UserId":"1" } in order for model binding to work.

Java RESTEasy WebService - Download the image file from HTTPResponse object.

I need to download a image files from the file system using RESTEasy web service and the input httpclient is JSON and the output response is
#Produces({"image/jpeg,image/png"})
Here is my client code:
public void getFileDownload(){
log("inside getServerPath....");
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(downloadWebService_URL);
JSONObject json = new JSONObject();
json.put("filePath", "/ngs/app/sample.png");
json.put("fileName", "sample.png");
log("json-->"+json.toString());
StringEntity inputJson = null;
try {
inputJson = new StringEntity(json.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
log("inputJson = " + inputJson.toString());
inputJson.setContentType("application/json");
httpPost.setEntity(inputJson);
httpPost.addHeader("AppType", "TC");
log("httpPost... httpPost");
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
log("response:-->"+response);
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (Exception e)
{
log("E:: " + ExceptionUtils.getStackTrace(e));
}
}
Here is my Webservice code:
#Path("/downloadservice")
public class DownloadFileWS {
private static final String FILE_PATH = "/ngs/app/sample.png";
#POST
// #Path("/images")
#Path("/{fileName}/images")
#Consumes({"application/json"})
#Produces({"image/jpeg,image/png"})
public Response getImageFile(#PathParam("fileName") String fileName) {
File file = new File(FILE_PATH);
System.out.println("File requested is : " + fileName);
Logger.getLogger("!!!!!!!!!!!"+FILE_PATH);
System.out.println("########"+FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition","attachment; filename=\"sample.png\"");
return response.build();
}
The HTTP Response is:
response:-->HTTP/1.1 200 OK [Date: Tue, 19 Jul 2016 00:36:22 GMT,
Content-Length: 6192, Content-Type: image/png, Content-Disposition:
attachment; filename="sample.png", X-Powered-By: Servlet/2.5 JSP/2.1]
org.apache.http.conn.BasicManagedEntity#2ace1307
Question:
1. Based on the response, it looks like the service is sending the image in HTTPResponse object. May i know how to download the image received from HTTP Response?
2. The requirement is to click a link which calls the webservice by passing JSON as input request and the image should automatically download to the user's local machine browser.

Windows.Web.HttpClient: Cookies will not be sent

I send a HTTP Get Request with a Basic Authentification to the Login-Endpoint of the Host:
request = new HttpRequestMessage();
// Configuration Item: Login URL Suffix
request.RequestUri = new Uri(string.Format("https://{0}/{1}", Host, loginSuffix));
request.Method = Windows.Web.Http.HttpMethod.Get;
var info = User + ":" + Password;
var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(info));
request.Headers.Authorization = new HttpCredentialsHeaderValue("Basic", token);
_httpClient = CreateHttpClient(ref cookieManager);
response = await _httpClient.SendRequestAsync(request, HttpCompletionOption.ResponseContentRead);
response.EnsureSuccessStatusCode();
responseBodyAsText = await response.Content.ReadAsStringAsync();
The HttpClient is created with a Filter, to set Cookies later:
private HttpClient CreateHttpClient(ref HttpCookieManager _cookieManager)
{
HttpBaseProtocolFilter _filter = new HttpBaseProtocolFilter();
HttpClient _httpClient = new Windows.Web.Http.HttpClient(_filter);
_cookieManager = _filter.CookieManager;
return _httpClient;
}
From the Response the SET-COOKIE Header can be read.
string[] Queries;
response.Headers.TryGetValue("Set-Cookie", out tmpString);
if (tmpString != null)
Queries = tmpString.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
I´m looking for a Cookie with a defined Name (CookieKeyName), which will be set in the next Request.
foreach (var query in Queries)
{
if (query.Contains(CookieKeyName))
{
staticCookieKey = query.Substring(0, query.IndexOf("="));
staticCookieValue = query.Substring(query.IndexOf("=") + 1);
}
}
I would expect, that the HttpClient will use the received Set-Cookie in the response for this URL as Cookie in every following Request automatically.
I´m preparing the next Request and setting the Cookie by myself:
request.RequestUri = new Uri(string.Format("https://{0}/qcbin", Host));
request.Method = Windows.Web.Http.HttpMethod.Get;
HttpCookie _cookie = new Windows.Web.Http.HttpCookie(staticCookieKey, Host, "/");
_cookie.Value = staticCookieValue;
bool replaced = cookieManager.SetCookie(_cookie);
The following Sending of the Requests provides to a Web Exception 401, because the Server expects for this URL the previously in the Response received Cookie.
response = await _httpClient.SendRequestAsync(request, HttpCompletionOption.ResponseContentRead);
response.EnsureSuccessStatusCode();
responseBodyAsText = await response.Content.ReadAsStringAsync();
Looking with Fiddler on the Line, the second Request contains no Cookie Header. Even Setting of the Cookie in CookieManager nor the proceeding of the Set-Cookie i the first Response by the HttpClient is working.
Hint: The length of the value of the Cookies is about 6000 chars (coming from a IBM Data Power).
Thank you in advance for help.

Asmx web service basic authentication

I want to implement basic authentication using username and password validation in my asmx web service.
I don't want to use WCF and I know this is not secure way, but I need to use basic authentication without using https.
My web service is like this:
[WebService(Namespace = "http://www.mywebsite.com/")]
public class Service1
{
[WebMethod]
public string HelloWorld()
{
return "Hello world";
}
}
And I use this custom HttpModule:
public class BasicAuthHttpModule : IHttpModule
{
void IHttpModule.Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(OnAuthenticateRequest);
}
void OnAuthenticateRequest(object sender, EventArgs e)
{
string header = HttpContext.Current.Request.Headers["Authorization"];
if (header != null && header.StartsWith("Basic")) //if has header
{
string encodedUserPass = header.Substring(6).Trim(); //remove the "Basic"
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string userPass = encoding.GetString(Convert.FromBase64String(encodedUserPass));
string[] credentials = userPass.Split(':');
string username = credentials[0];
string password = credentials[1];
if(!MyUserValidator.Validate(username, password))
{
HttpContext.Current.Response.StatusCode = 401;
HttpContext.Current.Response.End();
}
}
else
{
//send request header for the 1st round
HttpContext context = HttpContext.Current;
context.Response.StatusCode = 401;
context.Response.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", string.Empty));
}
}
void IHttpModule.Dispose()
{
}
}
And in the web.config I use this:
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<customErrors mode="Off" />
<compilation debug="true" targetFramework="4.0"/>
<authentication mode="None"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="BasicAuthHttpModule"
type="AuthService.BasicAuthHttpModule, AuthService" />
</modules>
</system.webServer>
</configuration>
The calling code is:
static void Main(string[] args)
{
var proxy = new Service1.Service1()
{
Credentials = new NetworkCredential("user1", "p#ssw0rd"),
PreAuthenticate = true
};
try
{
var result = proxy.HelloWorld();
Console.WriteLine(result);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
when I use this web service, the service asks for basic authentication but header variable in the OnAuthenticateRequest method always is null and MyUserValidator.Validate() never run.
EDIT
The fiddler results:
POST http://www.mywebsite.com/Service1.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.4927)
VsDebuggerCausalityData: uIDPo+drc57U77xGu/ZaOdYvw6IAAAAA8AjKQNpkV06FEWDEs2Oja2C+h3kM7dlDvnFfE1VlIIIACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://www.mywebsite.com/HelloWorld"
Host: www.mywebsite.com
Content-Length: 291
Expect: 100-continue
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><HelloWorld xmlns="http://www.mywebsite.com/" /></soap:Body></soap:Envelope>
HTTP/1.1 401 Unauthorized
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic realm=""
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Basic realm="www.mywebsite.com"
X-Powered-By: ASP.NET
Date: Sun, 03 Jun 2012 07:14:40 GMT
Content-Length: 1293
------------------------------------------------------------------
POST http://www.mywebsite.com/Service1.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.4927)
VsDebuggerCausalityData: uIDPo+drc57U77xGu/ZaOdYvw6IAAAAA8AjKQNpkV06FEWDEs2Oja2C+h3kM7dlDvnFfE1VlIIIACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://www.mywebsite.com/HelloWorld"
Authorization: Basic dXNlcjE6cEBzc3cwcmQ=
Host: www.mywebsite.com
Content-Length: 291
Expect: 100-continue
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><HelloWorld xmlns="http://www.mywebsite.com/" /></soap:Body></soap:Envelope>
HTTP/1.1 401 Unauthorized
Content-Type: text/html
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic realm="www.mywebsite.com"
X-Powered-By: ASP.NET
Date: Sun, 03 Jun 2012 07:14:41 GMT
Content-Length: 1293
------------------------------------------------------------------
Change your custom HttpModule code to this:
public class BasicAuthHttpModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication application)
{
application.AuthenticateRequest += new
EventHandler(this.OnAuthenticateRequest);
application.EndRequest += new
EventHandler(this.OnEndRequest);
}
public void OnAuthenticateRequest(object source, EventArgs
eventArgs)
{
HttpApplication app = (HttpApplication)source;
string authHeader = app.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authHeader))
{
string authStr = app.Request.Headers["Authorization"];
if (authStr == null || authStr.Length == 0)
{
return;
}
authStr = authStr.Trim();
if (authStr.IndexOf("Basic", 0) != 0)
{
return;
}
authStr = authStr.Trim();
string encodedCredentials = authStr.Substring(6);
byte[] decodedBytes =
Convert.FromBase64String(encodedCredentials);
string s = new ASCIIEncoding().GetString(decodedBytes);
string[] userPass = s.Split(new char[] { ':' });
string username = userPass[0];
string password = userPass[1];
if (!MyUserValidator.Validate(username, password))
{
DenyAccess(app);
return;
}
}
else
{
app.Response.StatusCode = 401;
app.Response.End();
}
}
public void OnEndRequest(object source, EventArgs eventArgs)
{
if (HttpContext.Current.Response.StatusCode == 401)
{
HttpContext context = HttpContext.Current;
context.Response.StatusCode = 401;
context.Response.AddHeader("WWW-Authenticate", "Basic Realm");
}
}
private void DenyAccess(HttpApplication app)
{
app.Response.StatusCode = 401;
app.Response.StatusDescription = "Access Denied";
app.Response.Write("401 Access Denied");
app.CompleteRequest();
}
}
Then enable Anonymous authentication and disable Basic, Digest and Windows authentication for your website in IIS.
Note: This implementation will work with WCF too.
It seems that you need send the headers manually the first time:
from Rick Strahl's Blog
string url = "http://rasnote/wconnect/admin/wc.wc?_maintain~ShowStatus";
HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest;
string user = "ricks";
string pwd = "secret";
string domain = "www.west-wind.com";
string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(user + ":" + pwd));
req.PreAuthenticate = true;
req.Headers.Add("Authorization", auth);
req.UserAgent = ": Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 4.0.20506)";
WebResponse resp = req.GetResponse();
resp.Close();

SOAPConnection not handling gzip response

I am using SOAPConnection to to invoke a SOAP based web service. The request is sent with "Accept-Encoding: gzip,deflate" in the header.
I used fiddler to grab the response, it is gzipped compressed, but while deserializing the message, the SOAPConnection is giving an error saying "invalid utf-8" message.
I tried normal http post and the http response is able to unzip the response correctly. Do I need to set some attributes on SOAPConnection to get it to handle the gzip message?
I found this snippet doing the job
SOAPMessage response = conn.call(finalRequest, aUrl);
// The response is gzip encoded, so decompress the response.
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.writeTo(out);
byte[] barr = out.toByteArray();
InputStream gzipStream = new GZIPInputStream(new ByteArrayInputStream(barr));
Reader decoder = new InputStreamReader(gzipStream, "UTF-8");
BufferedReader buffered = new BufferedReader(decoder);
int n = 0;
char[] cbuf = new char[1024];
Writer w = new StringWriter();
while ((n = buffered.read(cbuf)) != -1) {
w.write(cbuf,0,n);
}
// the writer now contains unzipped message.
System.out.println(w.toString());
GZIP Request,Response form Server:
If the server is enable with GZip then the server sends gzip-compress text data. For this we need over a request with Http headers as:
Request: We must send a HTTP request containing the Accept-Encoding: gzip header.
Response: If gzip is enabled, the server should return the Content-Encoding: gzip header.
Soap WebServies:
a - Grahical Weather Endpoint HTTPS and its WSDL URL OnlineClient
Response Headers:
Content-Type:text/xml; charset=ISO-8859-1
Vary:Accept-Encoding
Content-Encoding:gzip
Plain Response - DemoOnline Webserice HTTP. for example see stackpostResponse Headers: Content-Type:application/soap+xml; charset=utf-8
Request the WebService using SOAPConnectiona and get response in GZIP compressed format:
public static String getGZIP(byte[] zipBytes) {
try {
GZIPInputStream gzipInput = new GZIPInputStream( new ByteArrayInputStream(zipBytes) );
return IOUtils.toString(gzipInput);
} catch (IOException e) {
throw new UncheckedIOException("Error while decompression!", e);
}
}
public static void getSOAPConnection(SOAPMessage soapMsg) throws Exception {
System.out.println("\n===== SOAPConnection =====");
MimeHeaders headers = soapMsg.getMimeHeaders();
headers.addHeader("SoapBinding", serverDetails.get("SoapBinding") );
headers.addHeader("MethodName", serverDetails.get("MethodName") );
headers.addHeader("SOAPAction", serverDetails.get("SOAPAction") );
headers.addHeader("Content-Type", serverDetails.get("Content-Type")); // InBound
headers.addHeader("Accept-Encoding", serverDetails.get("Accept-Encoding")); // OutBound
if (soapMsg.saveRequired()) soapMsg.saveChanges();
/*SOAPMessage message = MessageFactory.newInstance().createMessage(headers, new ByteArrayInputStream(TSOXML.getBytes()));*/
SOAPConnectionFactory newInstance = SOAPConnectionFactory.newInstance();
javax.xml.soap.SOAPConnection connection = newInstance.createConnection();
SOAPMessage resp = connection.call(soapMsg, getURL( serverDetails.get("SoapServerURI") ));
MimeHeaders mimeHeaders = resp.getMimeHeaders();
String[] header = mimeHeaders.getHeader("Content-Encoding");
String contentEoncoding = "";
if (header != null && header.length > 0) contentEoncoding = header[0].toString();
System.out.println("Content:"+contentEoncoding);
if (contentEoncoding.equalsIgnoreCase("GZIP")) {
System.out.println("SOAP Message in GZIP");
ByteArrayOutputStream out = new ByteArrayOutputStream();
resp.writeTo(out);
byte[] zipBytes = out.toByteArray();
String gZipString= getGZIP(zipBytes);
System.out.println("Response:"+ gZipString);
SOAPMessage soapMessage = getSOAPMessagefromDataXML(gZipString);
System.out.println("SOAP Message Object:\n"+soapMessage);
getSOAPXMLasString(soapMessage);
} else {
getSOAPXMLasString(resp);
}
}
Requesting SOAP WS using HTTPCline. The way SOAPUI requests:
public static void getHttpURLConnection_Core(SOAPMessage soapMsg) throws Exception {
System.out.println("\n===== java.net.HttpURLConnection =====");
URL url = new URL(null, serverDetails.get("SoapServerURI"));
String protocol = url.getProtocol();
System.out.println("Protocol: "+protocol);
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_ADDRESS, PROXY_PORT));
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
connection.setReadTimeout(5 * 1000);
connection.setConnectTimeout(5 * 1000);
connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(true);
//String authString = username + ":" + password; // Authorization: Basic ZW9uMDE5XzAxOkVsaWFfMTIz
//String authMsg = "Basic " + Base64.encode(authString.getBytes());
//connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.AUTHORIZATION, authMsg);
((HttpURLConnection) connection).setRequestMethod("POST");
connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.ACCEPT, "text/xml");
connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.ACCEPT_LANGUAGE, "en-US,en;q=0.9");
connection.setRequestProperty("MethodName", serverDetails.get("MethodName") );
connection.setRequestProperty("SOAPAction", serverDetails.get("SOAPAction") );
connection.setRequestProperty("HTTP_ACCEPT_ENCODING", "gzip, deflate, br");
connection.setRequestProperty("Accept-Encoding", serverDetails.get("Accept-Encoding"));
String soapxmLasString = getSOAPXMLasString(soapMsg);
connection.setRequestProperty(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE, "text/xml");// serverDetails.get("Content-Type")
connection.setRequestProperty( "Content-Length", String.valueOf(soapxmLasString.length()));
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
try {
dataOutputStream.writeBytes(soapxmLasString);
} finally {
dataOutputStream.close();
}
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());
System.out.println("TIme taken Date:"+date+", Time:"+ (end-start));
String contentEncoding = connection.getContentEncoding();
System.out.println("Encoding:"+ contentEncoding);
int responseCode = connection.getResponseCode();
String responseMessage = connection.getResponseMessage();
System.out.println("Response Code: " + responseCode + " " + responseMessage);
String xmlRply = null ;
String requestStatus = "Fail";
if (responseCode == HttpURLConnection.HTTP_OK) {
requestStatus = "Pass";
InputStream inputStream = connection.getInputStream();
xmlRply = getStreamContent(inputStream, contentEncoding);
} else { // Response Code: 500 Internal Server Error
InputStream errorStream = connection.getErrorStream();
xmlRply = getStreamContent(errorStream, contentEncoding);
}
System.out.println("Reply: " + xmlRply);
System.out.println("Request Status:"+ requestStatus);
}
public static String getStreamContent(InputStream input, String encoding) throws IOException {
byte[] httpRply;
String rply;
httpRply = IOUtils.toByteArray(input);
System.out.println("Byte Array:"+httpRply.toString());
if (encoding == null) {
rply = new String(httpRply);
} else if ( encoding.equalsIgnoreCase("GZIP") ) {
rply = getGZIP(httpRply);
} else { // "ISO-8859-1", ";TF-8"
rply = new String(httpRply, encoding);
}
return rply;
}
Working example where the Server response with GZIP format.
public class SOAP_Weather {
static final String PROXY_ADDRESS = "Proxy_*****.net";
static final int PROXY_PORT = 9400;
static HashMap<String, String> serverDetails = new HashMap<>();
static {
// https://graphical.weather.gov/xml/ : conus
serverDetails.put("SoapServerURI", "https://graphical.weather.gov:443/xml/SOAP_server/ndfdXMLserver.php");
serverDetails.put("SoapWSDL", "https://graphical.weather.gov/xml/SOAP_server/ndfdXMLserver.php?wsdl");
serverDetails.put("SoapXML", "<ndf:CornerPoints xmlns:ndf=\"https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><sector xsi:type=\"xsd:string\">conus</sector></ndf:CornerPoints>");
serverDetails.put("SoapBinding", "ndfdXMLBinding");
serverDetails.put("MethodName", "CornerPoints");
serverDetails.put("SOAPAction", "https://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl#CornerPoints");
serverDetails.put("User-Agent", "Apache-HttpClient");
serverDetails.put("Accept-Encoding", "gzip,deflate,sdch");
serverDetails.put("Content-Type", "text/xml;charset=UTF-8");
}
public static void main(String[] args) throws Exception {
callSoapService();
}
public static void callSoapService( ) throws Exception{
String xmlData = serverDetails.get("SoapXML");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
dbFactory.setIgnoringComments(true);
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
Document docBody = dBuilder.parse(ips);
//docBody.createElementNS(DSIG_NS, "ds");
System.out.println("Data Document: "+docBody.getDocumentElement());
// Protocol 1.1=SOAP-ENV Content-Type:text/xml; charset=utf-8, 1.2=env Content-Type:application/soap+xml; charset=utf-8
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage soapMsg = messageFactory.createMessage();
SOAPPart soapPart = soapMsg.getSOAPPart();
SOAPEnvelope soapEnv = soapPart.getEnvelope();
SOAPBody soapBody = soapEnv.getBody();
soapBody.addDocument(docBody);
// Invoke the webService.
System.out.println("Request SOAP Message:");
soapMsg.writeTo(System.out);
System.out.println("\n");
// Protocol 1.1=SOAP-ENV Content-Type:text/xml; charset=utf-8, 1.2=env Content-Type:application/soap+xml; charset=utf-8
SOAPEnvelope envelope = soapMsg.getSOAPPart().getEnvelope();
if (envelope.getElementQName().getNamespaceURI().equals("http://schemas.xmlsoap.org/soap/envelope/")) {
System.out.println("SOAP 1.1 NamespaceURI: http://schemas.xmlsoap.org/soap/envelope/");
serverDetails.put("Content-Type", "text/xml; charset=utf-8");
} else {
System.out.println("SOAP 1.2 NamespaceURI: http://www.w3.org/2003/05/soap-envelope");
serverDetails.put("Content-Type", "application/soap+xml; charset=utf-8");
}
getSOAPConnection(soapMsg); // Disadvantage 1:
getHttpURLConnection_Core(soapMsg);
}
private static URL getURL(String endPointUrl) throws MalformedURLException {
URL endpoint = new URL(null, endPointUrl, new URLStreamHandler() {
protected URLConnection openConnection(URL url) throws IOException {
URL clone = new URL(url.toString());
URLConnection connection = null;
if (PROXY_ADDRESS != null && PROXY_PORT != 0 ) { // https://stackoverflow.com/a/22533464/5081877
Socket socket = new Socket();
SocketAddress sockaddr = new InetSocketAddress(PROXY_ADDRESS, PROXY_PORT);
socket.connect(sockaddr, 10000);
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(socket.getInetAddress(), PROXY_PORT));
if (proxy.address().toString().equals("0.0.0.0/0.0.0.0:80") || proxy.address().toString() != null) {
System.out.println("Connection through proxy ...");
connection = clone.openConnection(proxy);
} else {
connection = clone.openConnection();
}
} else {
connection = clone.openConnection();
}
connection.setConnectTimeout(5 * 1000); // 5 sec
connection.setReadTimeout(5 * 1000); // 5 sec
return connection;
}
});
return endpoint;
}
public static String getSOAPXMLasString(SOAPMessage soapMsg) throws SOAPException, IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
soapMsg.writeTo(out);
// resp.writeTo(System.out);
String strMsg = new String(out.toByteArray());
System.out.println("Soap XML: "+ strMsg);
return strMsg;
}
public static SOAPMessage getSOAPMessagefromDataXML(String saopBodyXML) throws Exception {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
dbFactory.setIgnoringComments(true);
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
InputSource ips = new org.xml.sax.InputSource(new StringReader(saopBodyXML));
Document docBody = dBuilder.parse(ips);
System.out.println("Data Document: "+docBody.getDocumentElement());
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage soapMsg = messageFactory.createMessage();
SOAPBody soapBody = soapMsg.getSOAPPart().getEnvelope().getBody();
soapBody.addDocument(docBody);
return soapMsg;
}
// SOPAConneciton and HTTPClien connection functions
}
did you see this?
SOAPMessage - SOAPConnection - gzip - how to
Also, if you use AXIS2, it has built-in features to enable compression of base64-encoded binary content using MTOM:
http://axis.apache.org/axis2/java/core/docs/mtom-guide.html
Just to complete that snippet - if you want to work with the decompressed SOAPMessage you need to load it into a new message.
SOAPMessage responseCompressed = connection.call(reqMessage, endpoint);
ByteArrayOutputStream out = new ByteArrayOutputStream();
responseCompressed.writeTo(out);
byte[] barr = out.toByteArray();
InputStream gzipStream = new GZIPInputStream(new ByteArrayInputStream(barr));
Here is the magic line
SOAPMessage response = factory.createMessage(responseCompressed.getMimeHeaders(), gzipStream);
Where factory is your MessageFactory.
Now response will function like it did without the gzip headers. You just drop it in.