I am trying to post images to an confluence page as attachment to a content.
Here is the function of my java application:
public void postAttachment(File f, String comment) throws IOException {
if (!f.exists() || !f.canRead()) {
throw new IOException("Could not access file " + f.getAbsolutePath());
}
final FileBody bin = new FileBody(f);
final StringBody cmt = new StringBody(comment, ContentType.TEXT_PLAIN);
final HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("file", bin).addPart("comment", cmt).build();
final HttpPost post = new HttpPost(baseUrl + "/rest/api/content/" + contentid + "/child/attachment");
post.setEntity(reqEntity);
post.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(props.getString("confluence_user"),props.getString("confluence_password")), "UTF-8", false));
post.addHeader("X-Atlassian-Token:","no-check");
System.out.println("executing request " + post.getRequestLine());
final CloseableHttpClient httpclient = HttpClients.createDefault();
final CloseableHttpResponse response = httpclient.execute(post);
System.out.println(post.getRequestLine());
System.out.println(response.toString());
if (response.getStatusLine().getStatusCode() == 404) {
throw new IOException("Status 404 thrown!");
}
}
The output in the terminal is:
POST https://xxx.xxxx.de:443/rest/api/content/38262140/child/attachment
and then
HttpResponseProxy{HTTP/1.1 404 Not Found [Server: Apache-Coyote/1.1, X-ASEN: SEN-1343236, Set-Cookie: JSESSIONID=9DF46011711C2828977E17A945D023E1; Path=/; Secure; HttpOnly, X-Seraph-LoginReason: OK, X-AUSERNAME: xxxx, X-Content-Type-Options: nosniff, Content-Type: text/plain, Transfer-Encoding: chunked, Date: Tue, 27 Sep 2016 11:20:35 GMT] ResponseEntityProxy{[Content-Type: text/plain,Chunked: true]}}
(I changed the domain name and username just for this post..)
So all seems ok. If i copy the generated POST url and do a GET in the browser i get a json snippet with an attachment list, manually uploaded before. So the POST url should be ok.
I searched across the web but i cant find where i am wrong with my code.. Any Suggestions?
Confluence is strict in "X-Atlassian-Token" header value. You have extra : in header name.
Change
post.addHeader("X-Atlassian-Token:","no-check");
to
post.addHeader("X-Atlassian-Token","no-check");
This will create correct header, and 404 error will go away
I too am presently struggling to add attachments; now on to a 403 Forbidden...
I worked through my 404 finding that it was in my (bad) URL. However, your URL does appear correct. Any chance that Page ID is off or your authenticated user lacks permissions (globally, in the space, or at the page level)?
Edit: Oh! And, as mtheriault's post suggests, check the attachment size vis a vis your Confluence instance's "attachmentMaxSize".
Related
I have the following implementation to get token from form authentication.
The expected output is as follows:
However, when I run my implementation, I am getting as follows. In the response object, I do not see token. I am not an expert on Java, I wonder what I am missing.
Login form get: HTTP/1.1 200 OK
response: HttpResponseProxy{HTTP/1.1 200 OK [Cache-Control: max-age=0, Content-Type: application/json, Date: Fri, 04 Aug 2017 21:05:04 GMT, transaction_id: 729097fd-69ac-b813-26c7-015daf10ddfd, X-Powered-By: Express, Content-Length: 684, Connection: keep-alive] ResponseEntityProxy{[Content-Type: application/json,Content-Length: 684,Chunked: false]}}
Post logon cookies:
None
Here is the source code:
BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build();
HttpHost proxy = new HttpHost("xxx.xxx.xxx.com", 80, "http");
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
HttpUriRequest login = RequestBuilder.post()
.setUri(new URI("https://api.xxx.com:443/tokens"))
.addParameter("username", "stackoverflow")
.addParameter("password", "isbest!")
.setConfig(config)
.build();
CloseableHttpResponse response2 = httpclient.execute(login);
HttpEntity entity = response2.getEntity();
System.out.println("Login form get: " + response2.getStatusLine());
EntityUtils.consume(entity);
System.out.println("response: " + response2);
System.out.println("Post logon cookies:");
List<Cookie> cookies = cookieStore.getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
When you call EntityUtils#consume(HttpEntity), you are fully consuming the content of the response and closing the underlying stream. However, you haven't actually read the response data into any variable accessible by your code, so you no longer have any opportunity to look at it.
Instead, call one of the methods that fetches the response data. Options for this include HttpEntity#getContent() to access the response body as a raw InputStream or EntityUtils#toString(HttpEntity, Charset) to read the whole response body as a String. (In the latter case, be aware that reading the whole response body at once as a String will impact your process's memory footprint if the response body is large.) After calling either one of those, you can pass the retrieved content through your JSON parser of choice to retrieve the "token".
Once you're all done, it's still good practice to call EntityUtils#consume(HttpEntity) to guarantee cleanup of any underlying resources encapsulated by the entity, such as streams.
I'm trying to make a POST request using JSON with foreign characters, such as the Spanish n with the '~' over it, but I keep getting this request and response error:
POST ...
Accept: application/json
Content-Type: application/json; charset=UTF-8
Content-Length: 151
Content-Encoding: UTF-8
Host: ...
Connection: Keep-Alive
User-Agent: ..
{"numbers":"2","date":"2014-07-15T00:00:00+0000","description":" // this never gets closed
X-Powered-By: ...
Set-Cookie: ...
Cache-Control: ...
Date: Tue, 15 Jul 2014 15:19:12 GMT
Content-Type: application/json
Allow: GET, POST
{"status":"error",
"status_code":400,
"status_text":"Bad Request",
"current_content":"",
"message":"Could not decode JSON, malformed UTF-8 characters (incorrectly encoded?)"}
I can already make a successful POST request with normal ASCII characters, but now that I'm supporting foreign languages, I need to convert the foreign characters to UTF-8 (or whatever the correct encoding ends up being), unless there's a better way to do this.
Here's my code:
JSONObject jsonObject = new JSONObject();
HttpResponse resp = null;
String urlrest = // some url;
HttpPost p = new HttpPost(urlrest);
HttpClient hc = new DefaultHttpClient();
hc = sslClient(hc);
try
{
p.setHeader("Accept", "application/json");
p.setHeader("Content-Type", "application/json");
// setting TimeZone stuff
jsonObject.put("date", date);
jsonObject.put("description", description);
jsonObject.put("numbers", numbers);
String seStr = jsonObject.toString();
StringEntity se = new StringEntity(seStr);
// Answer: The above line becomes new StringEntity(seStr, "UTF-8");
Header encoding = se.getContentType();
se.setContentEncoding("UTF-8");
se.setContentType("application/json");
p.setEntity(se);
resp = hc.execute(p);
When I put a breakpoint and look at se before it's submitted, the characters look right.
UPDATE: code updated with answer a few lines above with a comment identifying it.
The new StringEntity constructor takes a "UTF-8" parameter.
HAve re-written due to the feedback so far...
I'ev got a Java method to try and download a file via httpget within a selenium script, it looks like so...
private String downloader(WebElement element, String attribute, String filePath) throws IOException, NullPointerException, URISyntaxException {
String fileToDownloadLocation = element.getAttribute(attribute);
fileToDownloadLocation = fileToDownloadLocation.replace("\\", "%5C");
URL fileToDownload = new URL(fileToDownloadLocation);
URI FileDL = new URI(fileToDownload.toString());
File downloadedFile = new File(this.localDownloadPath + filePath);
if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);
CloseableHttpClient httpclient = HttpClients.createDefault();
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,new NTCredentials("useraccount", "testpassword", "machinename", "mydomain"));
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
HttpGet httpget = new HttpGet(FileDL);
CloseableHttpResponse response = httpclient.execute(httpget, context);
this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
response.getEntity().getContent().close();
String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
return downloadedFileAbsolutePath;
}
When I use this on a regular link (i.e. downloading a file from the bbc for example) it all works. The trouble is the system I'm using it on is an internal one that uses windows authentication to determine if access is permitted. When I attempt to use it on this internal system my Http response ends up reading: -
HTTP/1.1 401 Unauthorized [Cache-Control: no-cache, no-store, must-revalidate, Pragma: no-cache, Content-Type: text/html, Expires: -1, Server: Microsoft-IIS/7.5, WWW-Authenticate: Negotiate, WWW-Authenticate: NTLM, X-Powered-By: ASP.NET, X-UA-Compatible: IE=edge, Date: Mon, 17 Mar 2014 14:52:43 GMT, Content-Length: 1293]
If I debug this and obtain the URL it uses I can manually paste this into a browser and it works fine.
I also noticed that during debug the httpRequestParameters doesn't seem to have any values in in at all (shows as null) so I'm guessing that I'm still not setting the account parameters properly somehow.
I'll be honest and say I'm really not 100% on what all this does properly and am trying to paste things together and get it to play ball but I'm wondering if the section where I have ((AbstractHttpClient) client).getCredentialsProvider(). is set up properly or if I'm missing something here...
Any further help much appreciated!
You can set the BASIC authentication credentials in two different ways:
Setting the appropiated HTTP header:
HttpClient hc = new DefaultHttpClient();
HttpGet get = new HttpGet("http://...");
String basic_auth = new String(Base64.encodeBase64((username + ":" + password).getBytes()));
get.addHeader("Authorization", "Basic " + basic_auth);
or using the CredentialsProvider (depends on the Apache HttpComponents version)
HttpClient hc = new DefaultHttpClient();
hc.getCredentialsProvider().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("username", "password"));
HttpGet get = new HttpGet ("http://...");
hc.execute(get);
I've finally managed to get my code working, the final version is shown above. I'd made a few obvious errors such as my domain was still set to the examples "microsoft.com" and I had actually misspelled my password, other than that it now does exactly what I need it to! :)
#vzamanillo thanks for your help!
I have a Java application :
-this application send a String :
HttpClient httpClient = new DefaultHttpClient();
try {
HttpPost request = new HttpPost(url);
StringEntity params = new StringEntity(xml);
request.addHeader("content-type", "application/x-www-form-urlencoded");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// handle response here...
String res= response.toString();
System.out.println("RESPONSE=>\n"+response); //where i read the response
} catch (Exception ex) {
// handle exception here
} finally {
httpClient.getConnectionManager().shutdown();
}
I work with this String in my servlet and I just want to send a String response.
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("TEST");
But when i read the response i just have my header:
RESPONSE=>
HTTP/1.1 200 OK [X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7), Server: GlassFish Server Open Source Edition 3.1.2.2, Content-Type: text/html;charset=UTF-8, Content-Length: 83, Date: Fri, 14 Dec 2012 17:17:07 GMT]
Someone can help me ?
You are using the wrong method to read your response date. Calling:
String res= response.toString();
Just gives you the string representation of the Response object, not the data it contains. The Apache Http Commons library has a utility class that makes it easy to read responses, called EntityUtils. Use this instead to read the entire response body. Don't forget that you need to verify that the request actually completed successfully before doing this:
if(response.getStatusLine().getStatusCode() == 200) {
final String res = EntityUtils.toString(response.getEntity());
}
I posted before but now I seem to actually see the problem, just having trouble fixing it.
I am trying to login to my schools grade website, maybe even make an app for it later, and when I use Chrome to inspect the cookies being created, I get all these,
Cookie:appName=chippewa_falls; tool=""; selection=""; districtID=1; endYear=2011; calendarID=0; permCalendarID=0; JSESSIONID=BE5AEF51EAA72975150FC2D0F77DDE13
But when my program prints all the cookies it received, I only get this
[version: 0][name: JSESSIONID][value: BC1BAA33BEB23DC27B7883AC24934A1D][domain: campus.chipfalls.k12.wi.us][path: /campus][expiry: null]
here is my code,
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("https://campus.chipfalls.k12.wi.us/campus/portal/chippewa_falls.jsp");
httpget.addHeader("Referer", "http://cfsd.chipfalls.k12.wi.us//high/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println("Login form get: " + response.getStatusLine());
if (entity != null) {
InputStream input = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String ln = "";
while((ln = reader.readLine()) != null) {
System.out.println("During Get - " + ln);
}
}
System.out.println("Initial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
}
Note that is just for the GET part of it,
Thanks for any help :)
Edit: I did forget to mention, it is using HTTPS, but to be honest, I don't know if that matters with apache client or not.
Those cookies must be getting set AFTER you login, not before. Looking at the output with wget of the URL you have above you see this:
Resolving campus.chipfalls.k12.wi.us... 205.213.253.11
Connecting to campus.chipfalls.k12.wi.us|205.213.253.11|:443... connected.
WARNING: Certificate verification error for campus.chipfalls.k12.wi.us: self signed certificate in certificate chain
HTTP request sent, awaiting response...
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=004549BDBCBDFB8289EBF859A4E743B2; Path=/campus; Secure
Content-Type: text/html;charset=utf-8
Content-Length: 6352
Date: Tue, 17 May 2011 06:00:38 GMT
Connection: keep-alive
Length: 6,352 (6.2K) [text/html]
which is the exact same thing you see. Until you actually log in you will not see the other cookies.