I am trying to test a Servlet with special character which is deployed in jetty 9.
I am posting a String with a single quote character to the Servlet. Though I have mentioned to use UTF-8 character encoding in the Servlet , the Servlet cannot print the single quote character. I don't know what's wrong in the following code :
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SpecialCharacterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
BufferedReader in = new BufferedReader(
new InputStreamReader(request.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
in.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
The main method
public static void main(String s[]) {
try {
HttpURLConnection conn = (HttpURLConnection) new URL("http://localhost:8080/test/SpecialCharacterServlet").openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=*****");
String str = "Hello ‘World’";
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(str);
dos.flush();
dos.close();
InputStream is = conn.getInputStream();
byte[] content = new byte[is.available()];
is.read(content);
}catch(Exception e) {
System.out.println(e);
}
}
The output does not show the single quoted character , the output is Hello World , it's some block in there .
You need to remove any action where character sets are implied but not defined.
Ensure that you're Main.class is UTF-8 encoded.
Ensure that javac is aware that Main.class is UTF-8 encoded. Most IDE's do this for you but it requires you to set the encoding in the file properties
In main() wrap the OutputStream with OutputStreamWriter with an explicit charset declaration. This ensures everything written through the OutputStreamWriter is in the correct charset:
osw = OutputStreamWriter(conn.getOutputStream(), "UTF-8");
osw.write(str);
In your servlet, tell your inputStream to decode from "UTF-8":
BufferedReader in = new BufferedReader(
new InputStreamReader(request.getInputStream(), "UTF-8"));
System.out is also subject to charset conversion. This is particularly troublesome on DOS consoles. Instead, write the result to a text file and check the results in a good text editor, such as Notepad++. Again, when writing to the text file, set the character set in the constructor of your writer.
Related
I have code like this in JSR223 Sampler , and it gets passed also. But not able to see any output as response. Not sure what i have missed in it.
import android.util.Base64;
import java.security.spec.X509EncodedKeySpec;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import javax.crypto.Cipher;
String Original_String= ctx.getPreviousResult().getResponseDataAsString();
String Trim1=Original_String.substring(0, Original_String.lastIndexOf(","));
String Trim2=Trim1.replaceFirst("-----BEGIN PUBLIC KEY-----", "");
String Trim3=Trim2.replaceFirst("-----END PUBLIC KEY-----", "");
String[] parts = Trim3.split(":");
String myString = parts[1].substring(1, parts[1].length()-1);
String final_string=myString.replaceAll("\\\\n", "");
log.info(final_string);
String input="4000221111111111";
try{
byte[] byteKey = Base64.decode(final_string.getBytes(), Base64.DEFAULT);
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
Key k=kf.generatePublic(X509publicKey);
//return (PublicKey) k;
def cipher = Cipher.getInstance("RSA/NONE/OAEPPadding","BC");
cipher.init(Cipher.ENCRYPT_MODE, k);
byte[] encryptedBytes = cipher.doFinal(input.getBytes());
log.info( Base64.encodeToString(encryptedBytes, Base64.NO_WRAP));
}
catch(Exception e){
e.printStackTrace();
}
Could any one help me out on this Please ?
If you want your JSR223 Sampler to have response data you need to go for one of the following approaches:
return Base64.encodeToString(encryptedBytes, Base64.NO_WRAP)
or even better:
SampleResult.setResponseData(Base64.encodeToString(encryptedBytes, Base64.NO_WRAP), 'UTF-8')
See SampleResult class JavaDoc for all available functions, this way you have full control of response code, headers, body, message, etc.
You may also be interested in Apache Groovy - Why and How You Should Use It article which contains comprehensive information on Groovy scripting in JMeter tests.
I am using spring RestTemplate to download a file. The file size is small.
I want to get base64 encoded String. but I see the base64 encoded string is truncated from what it is supposed to be.
Here is my code
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(
new ByteArrayHttpMessageConverter());
StreamResourceReader reader = new StreamResourceReader();
restTemplate.execute(uri, HttpMethod.POST, null,
new StreamResponseExtractor(reader));
return reader.getEncodedString();
StreamResourceReader.java
public class StreamResourceReader {
private String encodeString;
public void read(InputStream content) {
try {
encodeString = Base64.encodeBase64String(IOUtils.toByteArray(content));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
public ByteArrayOutputStream getOutputStream(){
return outputStream;
}
public String getEncodedString() {
return encodeString;
}
}
StreamResponseExtractor.java
public class StreamResponseExtractor implements ResponseExtractor<InputStream> {
private StreamResourceReader reader;
public StreamResponseExtractor(StreamResourceReader resourceReader) {
this.reader=resourceReader;
}
#Override
public InputStream extractData(ClientHttpResponse response) throws IOException {
reader.read(response.getBody());
return null;
}
}
EDIT
just found out that inputStream is truncated. I dont know why and what the fix is. any help here would be appreciated.
Thanks
To confirm if your input stream is indeed truncated you can try few things. What IOUtils.toByteArray(content) does is buffers internally the content of input stream and returns the buffer. You can compare the length of buffer array with the byte array the file actually represents. You can do latter with below code
String filePath = "/test.txt";
byte[] fileByteArray= Files.readAllBytes(Paths.get(filePath));
Also ClientHttpResponse ( client view of http response) too has the inputstream available which you can check for content.
InputStream getBody() throws IOException;
As a test for this scenario , I created spring boot Rest client using Rest Template (using the code you shared) and a service for file download again using Spring Boot. On comparing the base encoded String from download vs direct file access, both return same content (compared using String equals method).
UPDATE: Another thing worth trying is just use java.net.HttpURLConnection
in a simple program (for help see here) and try to download the content and check whether this works properly because behind all the Spring abstractions, in this case the underlying object used is HttpURLConnection only
SimpleClientHttpResponse extends AbstractClientHttpResponse {
public InputStream getBody() throws IOException {
InputStream errorStream = this.connection.getErrorStream();
this.responseStream = (errorStream != null ? errorStream : this.connection.getInputStream());
return this.responseStream;
}
...........
...........
}
If this also gives you the same issue, then it's time to look at the server side. May be the server is not sending the complete data.
So this is the code I have:
public class PdfDownloaderServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws ServletException, IOException {
httpServletResponse.setContentType("application/pdf");
ServletContext servletContext = httpServletRequest.getServletContext();
InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/pdfs/x.pdf");
int read;
byte[] bytes = new byte[1024];
OutputStream os = httpServletResponse.getOutputStream();
while ((read = inputStream.read(bytes)) != -1) {
os.write(bytes, 0, read);
}
os.flush();
os.close();
}
}
and it works just fine.
However when I click the link that invokes this method, the browser will open the file, but I want the browser to directly download the file. How can I achieve this?
Thanks.
If you want the browser to download as attachment, you need to say so using the Content-Disposition header field. See http://greenbytes.de/tech/webdav/rfc6266.html#disposition.type, disposition type "attachment".
I am trying to write a http client which connects to a kerberos enabled tomcat(tested to be correct using browsers). It first gets the response code (which will be 401) and as according continue with its work.
The code is
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.*;
public class SampleHTTP2 {
static final String kuser = "correctusername"; // your account name
static final String kpass = "correctpassword"; // your password for the account
static class MyAuthenticator extends Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
//System.out.println("I am reaching here");
// I haven't checked getRequestingScheme() here, since for NTLM
// and Negotiate, the username and password are all the same.
System.err.println("Feeding username and password for "
+ getRequestingScheme());
return (new PasswordAuthentication(kuser, kpass.toCharArray()));
}
}
public static void main(String[] args) throws Exception {
URL url = new URL("http://mycompname:6008/examples/");
HttpURLConnection h1 = (HttpURLConnection) url.openConnection();
int rescode = h1.getResponseCode();
System.out.println(rescode);
System.setProperty("sun.security.krb5.debug", "true");
System.setProperty("java.security.auth.login.config", "C:\\login2.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly","false");
System.setProperty("java.security.krb5.conf", "C:\\krb5.ini");
if(rescode == 401){
Authenticator.setDefault(new MyAuthenticator());
URL url2 = new URL("http://mycompname/examples/");
URLConnection h2 = url2.openConnection();
InputStream ins2 = h2.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(ins2));
String str;
while((str = reader.readLine()) != null)
System.out.println(str);
}
}
}
Now when i comment the line:-
int rescode = h1.getResponseCode();
and put if(true) instead of if(rescode ==401), it works.
I am not sure what is going wrong. getResponseCode() internally calls getinputStream and thus I have used a separate url connection. Even still it does not work
P.S - Server is perfectly set up and the Authenticator class is also correct.
I am trying to create a UTF-8 file "myFile.aaa" using HttpServletResponse (HttpServlet). The reason why I need this to be UTF-8 is because it might contain special non-printable characters.
However, code below seems to create ANSI-encoded file. At least that is what Notepad++ says, and what I can see reading chars from this file. What am I doing wrong?
Thanks
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
res.setHeader("Content-Type", "application/octet-stream; charset=UTF-8");
res.setHeader("Content-Disposition","attachment;filename=myFile.aaa");
res.setCharacterEncoding("UTF-8");
ServletOutputStream os = res.getOutputStream();
os.print("Hello World");
os.flush();
os.close();
}
You need to use the character writer of the response, not the byte output stream.
Replace
ServletOutputStream os = res.getOutputStream();
os.print("Hello World");
os.flush();
os.close();
by
res.getWriter().write("Some UTF-8");
Further, I'd recommend setting content type to text/plain, not to an overly generic one which implies binary content, not character content.
I'm not sure about Notepad++, but in Notepad, if the text document does not contain any characters beyond the ANSI range, it will be interpreted as ANSI. Don't mislead you by this behaviour.
Here is my sample:
private static final String KALIMAH = "\u0644\u064e\u0622 \u0625\u0650\u0644\u0670\u0647\u064e \u0625\u0650\u0644\u0651\u064e\u0627 \u0627\u0644\u0644\u0647\u064f \u0645\u064f\u062d\u064e\u0645\u0651\u064e\u062f\u064c \u0631\u0651\u064e\u0633\u064f\u0648\u0652\u0644\u064f \u0627\u0644\u0644\u0647\u0650";
protected void printGreeting (HttpServletResponse res) throws IOException {
res.setContentType( "text/html" );
res.setCharacterEncoding( "UTF-8" );
PrintWriter out = res.getWriter();
out.write( KALIMAH );
out.close();
}