Jenkins plugin HttpRequest returns 500 error - jenkins-pipeline

I am writing a groovy script which has a method which is invoked from my Jenkins pipeline stage. This function calls an API which has a Basic Auth Header and a post body.
This piece of code returns me 500 on Jenkins, but works correct on Postman.
def callAPI(String SN_CREDENTIALS, String description, String name ) {
String auth = SN_CREDENTIALS.bytes.encodeBase64().toString()
def body_data = """{
"start_date": "${utc_startdate}",
"end_date": "${utc_enddate}",
"description": "${Description}",
}
"""
def url = 'https://example.com/api/sn_chg_rest/change/standard/' + id
def response = httpRequest url: url, acceptType: 'APPLICATION_JSON',
contentType: 'APPLICATION_JSON',
httpMode: 'POST',
requestBody: body_data,
customHeaders: [[name: 'Authorization', value: "Basic ${auth}"]]
}
where SN_CREDENTIALS are the credentials saved on Jenkins.
Jenkinsfile
environment {
SN_CREDENTIALS = credentials('SNCreds')
}
stage{
steps{
script{
buildTicketScript.callAPI("${SN_CREDENTIALS}",description,name)
}
}
}
Response Code: HTTP/1.1 500 Internal Server Error
Is there something wrong with the piece of code?

I found the issue. There was a problem with my body_data, one of the values had "new line" and it wasn't parsing it correctly. Removed the new line and it works perfectly fine

Related

Ajax PATCH/PUT problem 401 (Unauthorized)

I wrote an API using django and djano-ninja.
Here is my section of api.py file which is imported to URL.
class ORJSONRenderer(BaseRenderer):
media_type = "application/json"
def render(self, request, data, *, response_status):
return orjson.dumps(data)
class ApiKey(APIKeyQuery):
param_name = "api_key"
def authenticate(self, request, key):
try:
return CustomUser.objects.get(api_key=key)
except CustomUser.DoesNotExist:
pass
api_key = ApiKey()
api = NinjaAPI(
title="Good TExt",
version="0.0.1",
description="That This",
renderer=ORJSONRenderer(),
# csrf=True
)
#api.patch(
"/car/color/{new_color}", auth=api_key, tags=["Car"], summary="Does something",
description="Does something"
)
def update_team_name(request, new_color):
try:
#Do something
msg = {"success": "Done"}
except:
msg = {"error": "Problem"}
return HttpResponse(json.dumps(msg), content_type='application/json')
I have other get endpoints too. There is no problem when I request get endpoints.
But when I send a request to patch endpoints I am getting 401 (Unauthorized) only with ajax. I mean python's requests work.
import requests
load = dict(
api_key='SOME HEY'
)
r = requests.get("http://127.0.0.1:8000/api/car/color/red", params=load)
print(r.text)
But javascript doesn't:
$.ajax({
url: "/api/car/color/red",
data: {
"api_key": "some key"
},
cache: false,
type: "PATCH",
success: function(response_country) {
console.log(response_country);
},
error: function(xhr) {
console.log(xhr);
}
});
What I did try
I tried to add:
headers:{"X-CSRFToken": $crf_token},
to header of the ajax request. Even though csrf is set to False in django-ninja
I tried to change from PATCH to PUT
I tried to add a timeout to ajax request
I tried to send the api_key trough header and not the data
with no success.

Google Push notification giving ParseError

I am trying to use google push notification for calendar to be notified if a user's event's start or/and end dateTime changes.
I have followed all the steps from push doc regarding registering and verifying my domain.
My code is as follows:
#blueprint.route("/notifications", methods={'GET','POST'})
def timeBlocker():
email = '....#gmail.com'
user = User.query.filter_by(email=email).first()
thecredentials = {
'client_id': os.getenv('client_id'),
'client_secret':os.getenv('client_secret'),
'refresh_token':user.refresh,
'grant_type': 'refresh_token',
}
req = requests.post(url='https://oauth2.googleapis.com/token', data = thecredentials)
req_ = req.json()
accessToken = req_["access_token"]
print('access token is ' + accessToken)
body = {
'id': '01234567-89ab-cdef-0123456789ab',
'type': 'web_hook',
'address': 'https://dayliii.com/notifications'
}
headers = {'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json'
}
calendar = '....#group.calendar.google.com'
req = requests.post(url='https://www.googleapis.com/calendar/v3/calendars/....#group.calendar.google.com/events/watch', data = body, headers=headers)
return str(req.json())
Error:
{'error': {'errors': [{'domain': 'global', 'reason': 'parseError', 'message': 'Parse Error'}], 'code': 400, 'message': 'Parse Error'}}
I tried converting from double quotes to single quote as this similar post suggested yet it didn't work.
Lastly, I was curious to know if I should register & verify domain ownership of 'http://localhost:5000/' when working with push notifications in dev mode? As that's the error I am expecting to get that not sure about the way around it.
The data parameter in request() function accepts json format.
You can try converting your body variable into a json string using json.dumps().
Your request code should look like this:
req = requests.post(url='https://www.googleapis.com/calendar/v3/calendars/....#group.calendar.google.com/events/watch', data = json.dumps(body), headers=headers)

Subscribing to Angular 6 POST request

Scenario
I have an Angular 6 front end that communicates with a Spring Boot back end. The back end uses PostgreSQL as a database. The thing I want to do is to send a username to the data base and then return his email and print it on a page using Angular 6.
But, I am struggling with the Angular POST request where on subscribing to it I get a JSON parsing error in Chrome developer tools.
Code
Spring Boot
This works fine as I have tested it by printing the email returned from the database on the console.
#RequestMapping(value = "/reset", method = RequestMethod.POST)
public String resetMail(#RequestBody String username) {
try{
User user = userService.findByUsername(username);
//System.out.println(user.getEmail()); Testing purpose
return user.getEmail();
}catch(Exception e) {
//e.printStackTrace(); Prints out NullException StackTrace.
return "Not Present";
}
}
Angular 6
In the following code, I think the problem is in the subscription method as I am getting a JSON parsing error in Chrome developer tools.
httpOptions = { headers: new HttpHeaders({'Content-Type':'text/plain', 'Access-Control-Allow-Origin': '*'})};
reset(username:string) {
this.http.post('http://localhost:8090/reset', username, this.httpOptions).subscribe(data=> {
this.email = data as any;
});
}
console.log(this.email) // Prints undefined
Error
HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:8090/reset", ok: false, …}
>error: {error: SyntaxError: Unexpected token a in JSON at position 0 at JSON.parse (<anonymous>) at XMLHttp…, text: "abcdefg#yahoo.com"}
>headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure during parsing for http://localhost:8090/reset"
name: "HttpErrorResponse"
ok: false
status: 200
statusText: "OK"
url: "http://localhost:8090/reset"
You want to serialize a string to JSON. If your controller would return an object the #RestController annotation would serialize it properly. In case you want to return just a string you have to return JSONObject.quote(user.getEmail()); You can get the JSONObject dependency from here http://mvnrepository.com/artifact/org.json/json
But I encourage you to always return objects as a response from your rest controllers.

How to call a https POST method using gatewayscript in IBM Bluemix APIConnect

I am trying to call another API inside Bluemix or any other HTTPS post method using a gateway script inside IBM Bluemix (API Connect) using the code below:
var urlopen = require('urlopen');
var options = {
target: 'https://pokemons.mybluemix.net/api/pokemons/1',
method: 'POST',
headers: {},
contentType: 'application/json',
timeout: 60,
data: {"Message": "DataPower GatewayScript"}
};
urlopen.open(options, function(error, response) {
if (error) {
// an error occurred during the request sending or response header parsing
session.output.write("urlopen error: "+JSON.stringify(error));
} else {
// get the response status code
var responseStatusCode = response.statusCode;
var responseReasonPhrase = response.reasonPhrase;
console.log("Response status code: " + responseStatusCode);
console.log("Response reason phrase: " + responseReasonPhrase);
// reading response data
response.readAsBuffer(function(error, responseData){
if (error){
throw error ;
} else {
session.output.write(responseData) ;
apim.output('application/json');
}
});
}
});
But I am getting the following error:
{
"httpCode": "500",
"httpMessage": "Internal Server Error",
"moreInformation": "URL open: Cannot create connection to 'https://pokemons.mybluemix.net/api/pokemons/1', status code: 7"
}
Looks like there is some issue with the SSL Connections. If so, how can I get the SSL Details for the default Sandbox Catalog in IBM Bluemix API Connect? Or, how can I make the HTTPS POST calls to the above sample URL?
Since Version 5.0.6:
IBM API Connect 5.0.x
Forward SSLProxy (and Crypto) is replaced with SSLClient. These new profiles support ephemeral ciphers (DHE and ECDHE), perfect forward secrecy, and Server Name Indication (SNI) extension. Note that DHE ciphers in DataPower SSLServerProfile use 2048-bit DH parameters (as server) and accept 1024-bit DH parameters (as client).
In order for you specific example to work on API Connect using HTTPS you need to specify the sslClientProfile.
For example:
var urlopen = require('urlopen');
var options = {
target: 'https://pokemons.mybluemix.net/api/pokemons/1',
method: 'POST',
headers: {},
contentType: 'application/json',
timeout: 60,
sslClientProfile: 'webapi-sslcli-mgmt',
data: {"Message": "DataPower GatewayScript"}
};

CSRF Failed when POST data using Alamofire

I using django-reat-framework as backend and using SessionAuthentication and TokenAuthentication.
This work well when I use httpie send request
http POST http://127.0.0.1:8000/api/users/ email="abc#abc.com" user_name="abc" passwod="1234"
but when I use Alamofire
Alamofire.request(.POST, "http://127.0.0.1:8000/api/users/", parameters: ["email": emailField.text!, "user_name": usernameField.text!, "password": passwordField.text!], encoding: .URL )
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result)
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
return this
Optional(<NSMutableURLRequest: 0x7fe24e15d640> { URL: http://127.0.0.1:8000/api/users/ })
Optional(<NSHTTPURLResponse: 0x7fe24bf3a080> { URL: http://127.0.0.1:8000/api/users/ } { status code: 403, headers {
Allow = "GET, POST, HEAD, OPTIONS";
"Content-Type" = "application/json";
Date = "Fri, 11 Mar 2016 13:09:59 GMT";
Server = "WSGIServer/0.2 CPython/3.4.3";
Vary = "Accept, Cookie";
"X-Frame-Options" = SAMEORIGIN;
} })
Optional(<7b226465 7461696c 223a2243 53524620 4661696c 65643a20 43535246 20746f6b 656e206d 69737369 6e67206f 7220696e 636f7272 6563742e 227d>)
SUCCESS
JSON: {
detail = "CSRF Failed: CSRF token missing or incorrect.";
}
But 127.0.0.1:8000/api/users/ don't need any permission, and I didn't send csrf token when I using httpie.So, What's wrong here?
This header worked for me:
let headers = [
"Cookie": ""
]
Alamofire.request(urlString, method: .post, parameters: ["username": username!, "password": password!],encoding: JSONEncoding.default, headers: headers).responseJSON {
response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
From here: https://github.com/Alamofire/Alamofire/issues/646
POST/DELETE requests to API created using Django need a valid csrftoken to be passed along with the request.
You need to generate the token before you make any POST calls. To generate the token please refer to
https://docs.djangoproject.com/en/1.9/ref/csrf/
Also after getting the csrftoken value from the cookie, pass the token in the header of the request
let headers = [ "Accept":"application/json" , "Content-Type": "application/json" , "X-CSRFToken" : csrftoken]
Alamofire.request(.POST, "http://127.0.0.1:8000/api/users/", headers: headers, parameters: params, encoding: .JSON)
.validate()
.responseJSON { response in
switch response.result {
case .Success(let responseContent):
Take off SessionAuthentication from authentication_classes in the corresponding API view. It will "disable" cookies for this view, which means CSRF-token won't be required anymore.

Resources