Groovy Httpbuilder authentication with Realm + RABBIT MQ - grails

I am trying to to make a rabbitmq http api call to know how queues are there and other infos...
I need 3 variables to pass on to the api
1) url: (http://localhost:55672/api) 2) username/password: guest/guest
3) realm: "RabbitMQ Management" //i am not sure if this is important
4) path: "/queues"
when i make curl statement it gives a positive response
sudo curl -i -u guest:guest (http://localhost:55672)/api/queues
HTTP/1.1 200 OK
Server: MochiWeb/1.1 WebMachine/1.7 (participate in the frantic)
Date: Tue, 03 Jul 2012 01:39:05 GMT
Content-Type: application/json
Content-Length: 6176
Cache-Control: no-cache
but using httpbuilder from groovy. here is the code
def http = new HTTPBuilder("(http://localhost:55672/api)")
http.auth.basic 'guest','guest'
http.request(GET) { req ->
uri.path = '/queues'
response.success = { resp, reader ->
assert resp.statusLine.statusCode == 200
println "Got response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
println reader.json
}
response.'404' = { println 'Not found' }
}
I am getting "not found" as the result. I am not including realm because I am unable to if i can insert "realm" in httpbuilder. it only comes with OAuth however I need to use basic auth for rabbit mq http api calls.
Does anyone knows how to include realm name in httpbuilder groovy for basic authentication? is there any other way. Kindly let me know! thanks!

Does this work?
def http = new HTTPBuilder( 'http://localhost:55672' )
http.auth.basic 'guest','guest'
http.request(GET) { req ->
uri.path = '/api/queues'
response.success = { resp, reader ->
assert resp.statusLine.statusCode == 200
println "Got response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
println reader.json
}
response.'404' = { println 'Not found' }
}
Took the braces and the path out of your base url, added /api to the path

Related

HTTP NTLM authentication in jenkins pipeline script

I am trying to post request which requires NTLM authentication. The curl command works fine when i do post call but same method request won't work with jenkins pipeline script.
Curl command:
curl -X POST -k -v -H \"Content-Type: application/json\" -H \"Content-Length: 0\" --ntlm -u domain/username:password http://blrapi/ExeWebAPI/testplans/run/username/89cd1093-6558-4321-b689-cb1
Jenkins Pipeline code
def getClient(){
def server = ""
def username = "username"
def userpassword = "password"
def domain = "domain"
def client = new HttpClient()
client.state.setCredentials(
AuthScope.ANY,
new NTCredentials(username, password, "", domain)
)
return client
}
def RunPlan( planId ){
SknetPost("hhttp://blrapi/ExeWebAPI/testplans/run/username/89cd1093-6558-4321-b689-cb1","")
}
def skynetExecute(httpMethod){
def httpResponse = ""
def sknetClient = getClient()
try {
int result = sknetClient.executeMethod(httpMethod)
println "Return code: ${result}"
httpResponse = httpMethod.getResponseBodyAsString()
}
finally {
httpMethod.releaseConnection()
}
return httpResponse
}
void SknetPost(url, jsondata) {
def post = new PostMethod( url )
post.doAuthentication = true
post.setRequestHeader("Content-type", "application/json")
StringRequestEntity requestEntity = new StringRequestEntity( jsonData , "text/html", "UTF-8");
post.setRequestEntity(requestEntity);
httpResponse = sknetExecute(post)
return httpResponse
}
}
When i execute the program it gives 401- unauthorized access error. Same credentials were used curl command it works fine but in jenkins pipeline it fails.
Please help me to solve this issue.
Web requests with NTLM authentication from Jenkins pipeline could be realized with the HTTP Request Plugin.
Add the Credential (user/password) in the jenkins credential store.
You could then use httpRequest in your pipeline:
script {
def response = httpRequest httpMode: 'GET',
url: "http://localhost:80",
authentication: '3bb9use-your-id-from-store',
useNtlm: true
println("Status: "+response.status)
println("Content: "+response.content)
}
Regards.
work for me with jenkins 2.324, HTTP Request Plugin 1.12

Uploading txt file via POST request with HttpBuilder

I want to upload a txt file to a website using a POST request with HTTPBuilder and multipart/form-data
I've tried running my function and I get a HTTP 200 OK response, but the file doesn't appear on the website anywhere.
private Map fileUpload(String url, File file){
log.debug "doPost: $url body: ${file.getName()}"
FileBody fileBody = new FileBody(file,ContentType.APPLICATION_OCTET_STREAM)
def result = [:]
try {
def authSite = new HTTPBuilder(url)
authSite.auth.basic(user, password)
authSite.request(POST) { req ->
headers.Accept = "application/json, text/javascript, */*; q=0.01"
req.params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 20000)
req.params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 60000)
def mpe = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE)
mpe.addPart("gxt",fileBody)
req.setEntity(mpe)
response.success = { resp, reader ->
result = reader
}
response.failure = { resp, reader ->
println "My response handler got response: ${resp.statusLine}"
}
}
}
catch (e) {
log.debug("Could not perform POST request on URL $url", e)
throw e
}
return result
}
From debugging this is the status recieved
3695 [main] DEBUG org.apache.http.wire - << "HTTP/1.1 200 OK[\r][\n]"
3695 [main] DEBUG org.apache.http.wire - << "Date: Thu, 10 Jan 2019 07:34:06 GMT[\r][\n]"
Anything I'm doing wrong? I don't get any errors but it just seems like nothing happens.
I don't have anything conclusive, but I suspect there is something invalid with the way you set up the multipart upload.
To help figure this out, below is a standalone, working, multipart upload groovy script using HttpBuilder:
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
#Grab('org.apache.httpcomponents:httpmime:4.2.1')
import org.apache.http.entity.mime.content.*
import org.apache.http.entity.mime.*
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.Method.POST
fileUpload('https://httpbin.org/post', new File('data.txt'))
Map fileUpload(String url, File file){
println "doPost: $url body: ${file.name}"
def result
try {
new HTTPBuilder(url).request(POST) { req ->
requestContentType = "multipart/form-data"
def content = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE)
content.addPart(file.name, new InputStreamBody(file.newInputStream(), file.name))
req.entity = content
// json might be something else (like a reader)
// depending on the response content type
response.success = { resp, json ->
result = json
println "RESP: ${resp.statusLine}, RESULT: $json"
}
response.failure = { resp, json ->
println "My response handler got response: ${resp.statusLine}"
}
}
} catch (e) {
println "Could not perform POST request on URL $url"
throw e
}
result
}
The script assumes a file data.txt with the data to post in the current directory. The script posts to httpbin.org as a working test endpoint, adjust accordingly to post to your endpoint instead.
Saving the above in test.groovy and executing will yield something like:
~> groovy test.groovy
doPost: https://httpbin.org/post body: data.txt
RESP: HTTP/1.1 200 OK, RESULT: [args:[:], data:, files:[data.txt:{ "foo": "bar" }], form:[:], headers:[Accept:*/*, Connection:close, Content-Type:multipart/form-data; boundary=ZVZuV5HAdPOt2Sv7ZjxuUHjd8sDAzCz9VkTqpJYP, Host:httpbin.org, Transfer-Encoding:chunked], json:null, origin:80.252.172.140, url:https://httpbin.org/post]
(note that first run will take a while as groovy grapes need to download the http-builder dependency tree)
perhaps starting with this working example and working your way back to your code would help you pinpoint whatever is not working in your code.

Response zip file with WebFlux

I am new in Spring 5 and Reactive Programming. My problem is creating the export feature for the database by a rest API.
User hits GET request -> Server reads data and returns data as a zip file. Because zip file is large, so I need to stream these data.
My code as below:
#GetMapping(
value = "/export",
produces = ["application/octet-stream"],
headers = [
"Content-Disposition: attachment; filename=\"result.zip\"",
"Content-Type: application/zip"])
fun streamData(): Flux<Resource> = service.export()
I use curl as below:
curl http://localhost/export -H "Accept: application/octet-stream"
But it always returns 406 Not Acceptable.
Anyone helps?
Thank you so much
The headers attribute of the #GetMapping annotation are not headers that should be written to the HTTP response, but mapping headers. This means that your #GetMapping annotation requires the HTTP request to contain the headers you've listed. This is why the request is actually not mapped to your controller handler.
Now your handler return type does not look right - Flux<Resource> means that you intend to return 0..* Resource instances and that they should be serialized. In this case, a return type like ResponseEntity<Resource> is probably a better choice since you'll be able to set response headers on the ResponseEntity and set its body with a Resource.
Is it right, man? I still feel it's not good with this solution at the last line when using blockLast.
#GetMapping("/vehicle/gpsevent", produces = ["application/octet-stream"])
fun streamToZip(): ResponseEntity<FileSystemResource> {
val zipFile = FileSystemResource("result.zip")
val out = ZipOutputStream(FileOutputStream(zipFile.file))
return ResponseEntity
.ok().cacheControl(CacheControl.noCache())
.header("Content-Type", "application/octet-stream")
.header("Content-Disposition", "attachment; filename=result.zip")
.body(ieService.export()
.doOnNext { print(it.key.vehicleId) }
.doOnNext { it -> out.putNextEntry(ZipEntry(it.key.vehicleId.toString() + ".json")) }
.doOnNext { out.write(it.toJsonString().toByteArray(charset("UTF-8"))) }
.doOnNext { out.flush() }
.doOnNext { out.closeEntry() }
.map { zipFile }
.doOnComplete { out.close() }
.log()
.blockLast()
)
}

QuickBooks Authentication error when getting basic company information

I'm writing a simple desktop application to get information from QuickBooks(developer account using demo account(UK) data) and in this regard I've been able to go past the OAuth flow. However, I've not been able to get the basic company information
The below is a capture of the Fiddler request and response:
GET https://quickbooks.api.intuit.com/v3/company/123145829830639/companyInfo/123145829830639 HTTP/1.1
Authorization: oauth_token="****", oauth_nonce="z4x0a196", oauth_consumer_key="****", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1499283607", oauth_version="1.0", oauth_signature="EGw6Ty%2BKFAawrH1%2FSxQuFwaMcEo%3D"
Content-Type: application/json
Host: quickbooks.api.intuit.com
The generation of the header is similar to https://developer.intuit.com/v2/apiexplorer?apiname=V3QBO#?id=CompanyInfo but I end up getting the following response(Fiddler partial response) based on the request
intuit_tid: gw-c4e19f89-df78-42a5-ae7e-216187421143
Set-Cookie: JSESSIONID=21BF1FFEE48B39538E82485FD25C4280.c51-pprdsbxas901; Path=/; Secure; HttpOnly
QBO-Version: 1706.912
ErrorCode: 100
ErrorCause: AuthenticationErrorGeneral: SRV-110-Authentication Failure , statusCode: 401
Message: General Authentication Error
The code to access company information is as below:
string companyInfo = String.Format("company/{0}/companyInfo/{0}", authenticator.OAuthProfile.realmId);
string ciUrl = BASE_URL + companyInfo; //https://quickbooks.api.intuit.com/v3/
var sb = new System.Text.StringBuilder();
sb.AppendFormat("oauth_token=\"{0}\", oauth_nonce=\"{1}\", oauth_consumer_key=\"{2}\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"{3}\", oauth_version=\"1.0\", oauth_signature=\"{4}\"",
Manager.UrlEncode(_token),
Manager.UrlEncode(_nonce),
Manager.UrlEncode(_consumer_key),
Manager.UrlEncode(_timestamp),
Manager.UrlEncode(_signature));
var authorisationHeader = sb.ToString().TrimEnd(' ').TrimEnd(',');
// Request Company Information
var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(ciUrl);
request.Headers.Add("Authorization", authorisationHeader);
request.Method = "GET";
request.ContentType = "application/json";
using (var response = (System.Net.HttpWebResponse)request.GetResponse())
{
// get 401
}
Used sandbox URL and added minorversion to the base URL
I attempted setting BASE_URL set to the sandbox url(https://sandbox-quickbooks.api.intuit.com/v3) and also set minorversion to be 4.
Any help is much appreciated.
Hopefully this helps, but here is a Java snippet using their SDK that works for me:
OAuthAuthorizer oauth = new OAuthAuthorizer(System.env.QB_OAUTH_CONSUMER_KEY, System.env.QB_OAUTH_CONSUMER_SECRET,
vendor.intuitOAuthAccessToken, vendor.intuitOAuthAccessSecret);
UUID trackingID = UUID.randomUUID()
log.info("About to init Context companyID=" + vendor.realmId + ", app_token=" + System.env.QB_APP_TOKEN + ", uuid=" + trackingID.toString())
Context context = new Context(oauth, System.env.QB_APP_TOKEN, ServiceType.QBO, vendor.realmId)
context.setMinorVersion("4")
context.setTrackingID(trackingID)
log.info("About to set BaseURL")
Config.setProperty(Config.BASE_URL_QBO, System.env.QB_BASE_URL + "/v3/company");
log.info("About to init DataService")
// get all customers
log.info("About to executeQuery")
DataService service = new DataService(context)
QueryResult queryResult = service.executeQuery("select * from customer");
In my case, QB_BASE_URL=https://sandbox-quickbooks.api.intuit.com
*NOTE there isn't a trailing slash
vendor.intuitOAuthAccessToken and vendor.intuitOAuthAccessSecret are the values you get back after the oauth flow

io9 - Alamofire token request fails with 401 error depsite curl from debugPrint works

My question is along the line of a question which has been asked before at Previous question.
I am using Alamofire 3.2.1, XCode 7.3, iOS9.
Here is my code with the intention to obtain a token from OAuth server (localhost) implemented by django oauth toolkit:
let params = ["grant_type": "password",
"username": "rosa",
"password": "rosa1234"]
let request = Alamofire.request(.POST, url, parameters: params).authenticate(user: __clientID, password: __clientSecret)
debugPrint(request)
request.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseSwiftyJSON({ (request, response, json, error) in
debugPrint(response)
if (error != nil) {
print(error.debugDescription)
return completionHandler(token: nil, error: error)
}
// call the completionHandler function (object) to deal with data further
return completionHandler(token: json.string, error: nil)
})
The debug print of request gives a working curl command, which works on a command line:
curl -i \
-X POST \
-u PrtRUN9ra7LHCYWbiReaAjO9I26lJhLhRSAUJgtr:kTvxqKmClDAL3tbdyZdyBZgsfsfXtagMpZyFjSZwpIknxM43l6ZIvJxJGXu2J2FuHf4JMLfopDoAzkF6vHSRq4GZkbnEZSmmUnMvkhMvSucbhWUdzCpxuj9qtc8beaQ3 \
-H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" \
-H "User-Agent: IntelliCafe/xsoft.IntelliCafe (1; OS Version 9.3 (Build 13E230))" \
-H "Accept-Encoding: gzip;q=1.0, compress;q=0.5" \
-H "Accept-Language: en-US;q=1.0" \
-d "grant_type=password&password=rosa1234&username=rosa" \
"http://localhost:8000/o/token/"
But the code does not work in my app. The error is 401:
Optional(<NSHTTPURLResponse: 0x7d183950> { URL: http://localhost:8000/o/token/ } { status code: 401, headers {
"Cache-Control" = "no-store";
"Content-Type" = "application/json";
Date = "Mon, 11 Apr 2016 20:43:48 GMT";
Pragma = "no-cache";
Server = "WSGIServer/0.1 Python/2.7.10";
"X-Frame-Options" = SAMEORIGIN;} })
Optional(Error Domain=com.alamofire.error Code=-6003 "Response status code was unacceptable: 401" UserInfo={NSLocalizedFailureReason=Response status code was unacceptable: 401})
This problem is driving me crazy. Any help will be grateful!
Thanks in advance.
I wrote a django rest view to print out the meta data of the request and found out the clientID and clientSecret are not embedded/processed properly by the django server implementation.
Using the Authorization header as shown in Alamofire documentation works.

Resources