Setting headers to HttpResponse in akka - scala

I'm trying to set headers to HttpResponse
var response = HttpResponse()
val acrh = request.headers.filter(q => q.name() == "Access-Control-Request-Headers").head.value()
response = response.addHeader(`Access-Control-Allow-Headers`(acrh))
response = response.addHeader(`Access-Control-Request-Headers`(acrh))
In response I can see only "Access-Control-Allow-Headers", and I'm getting this error
"HTTP header 'Access-Control-Request-Headers' is not allowed in responses".
How can I solve this problem? I need to implement this for CORS.

Related

How to check for proper format in my API response

Currently running tests for my REST API which:
takes an endpoint from the user
using that endpoint, grabs info from a server
sends it to another server to be translated
then proceeds to jsonify the data.
I've written a series of automated tests running and I cannot get one to pass - the test that actually identifies the content of the response. I've tried including several variations of what the test is expecting but I feel it's the actual implementation that's the issue. Here's the expected API response from the client request:
{ "name": "random_character", "description": "Translated description of requested character is output here" }
Here is the testing class inside my test_main.py:
class Test_functions(unittest.TestCase):
# checking if response of 200 is returned
def test_healthcheck_PokeAPI(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/")
status_code = response.status_code
self.assertEqual(status_code, 200)
# the status code should be a redirect i.e. 308; so I made a separate test for this
def test_healthcheck_ShakesprAPI(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertEqual(response.status_code, 308)
def test_response_content(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertEqual(response.content_type,
'application/json') <<<< this test is failing
def test_trans_shakespeare_response(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertFalse(b"doth" in response.data)
Traceback:
AssertionError: 'text/html; charset=utf-8' != 'application/json' - text/html; charset=utf-8 + application/json
Any help would be greatly appreciated

Groovy script for Jenkins: execute HTTP request without 3rd party libraries

I need to create a Groovy post build script in Jenkins and I need to make a request without using any 3rd party libraries as those can't be referenced from Jenkins.
I tried something like this:
def connection = new URL( "https://query.yahooapis.com/v1/public/yql?q=" +
URLEncoder.encode(
"select wind from weather.forecast where woeid in " + "(select woeid from geo.places(1) where text='chicago, il')",
'UTF-8' ) )
.openConnection() as HttpURLConnection
// set some headers
connection.setRequestProperty( 'User-Agent', 'groovy-2.4.4' )
connection.setRequestProperty( 'Accept', 'application/json' )
// get the response code - automatically sends the request
println connection.responseCode + ": " + connection.inputStream.text
but I also need to pass a JSON in the POST request and I'm not sure how I can do that. Any suggestion appreciated.
Executing POST request is pretty similar to a GET one, for example:
import groovy.json.JsonSlurper
// POST example
try {
def body = '{"id": 120}'
def http = new URL("http://localhost:8080/your/target/url").openConnection() as HttpURLConnection
http.setRequestMethod('POST')
http.setDoOutput(true)
http.setRequestProperty("Accept", 'application/json')
http.setRequestProperty("Content-Type", 'application/json')
http.outputStream.write(body.getBytes("UTF-8"))
http.connect()
def response = [:]
if (http.responseCode == 200) {
response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))
} else {
response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))
}
println "response: ${response}"
} catch (Exception e) {
// handle exception, e.g. Host unreachable, timeout etc.
}
There are two main differences comparing to GET request example:
You have to set HTTP method to POST
http.setRequestMethod('POST')
You write your POST body to outputStream:
http.outputStream.write(body.getBytes("UTF-8"))
where body might be a JSON represented as string:
def body = '{"id": 120}'
Eventually it's good practice to check what HTTP status code returned: in case of e.g. HTTP 200 OK you will get your response from inputStream while in case of any error like 404, 500 etc. you will get your error response body from errorStream.

Akka HTTP how to POST singleRequest with Content-Type application/x-www-form-urlencoded

I stuck with sending request with Akka HTTP singleRequest(). I'm trying to deal with Stripe API and it requires application/x-www-form-urlencoded content type for the incoming requests.
I tried to use following structure of HTTP request:
val authorization = Authorization(OAuth2BearerToken("some_token"))
Http().singleRequest(HttpRequest(
uri = Uri("https://api.stripe.com/v1/customers"),
method = HttpMethods.POST,
headers = List(authorization),
entity = FormData(Map("email" -> HttpEntity("test_1#email.com"))).toEntity(),
protocol = HttpProtocols.`HTTP/1.1`)
)
But in the Stripe logs I see following in the Parsed Request POST Body section:
(multipart form: 162)
So the question is how to set content type to application/x-www-form-urlencoded?
The problem was related to FormData type. In order to perform application/x-www-form-urlencoded request you need to use FromData from package akka.http.scaladsl.model
So here is working example:
Http().singleRequest(HttpRequest(
uri = Uri("https://api.stripe.com/v1/customers"),
method = HttpMethods.POST,
headers = List(authorization),
entity = akka.http.scaladsl.model.FormData(Map("email" -> "user#email.com")).toEntity(HttpCharsets.`UTF-8`),
protocol = HttpProtocols.`HTTP/1.1`)
)

Scala HttpPost - How to pass authentication parameters

------Update
Was able to fix it by using the UsernamePasswordCredentials class
The code looks like below
val client = new DefaultHttpClient
client.getCredentialsProvider().setCredentials(AuthScope.ANY,new UsernamePasswordCredentials("user","password"));
i am trying to make a HttpPost call to a Restful API, its expecting a username/password, how to pass those parameters? I tried 2 ways
post.addHeader("Username","user")
post.addHeader("Password","clear pwd")
and
post.addHeader("Authorization","Basic base64encoded username:password")
nothing works, I get response text as
Response Text = HTTP/1.1 401 Unauthorized [WWW-Authenticate: Digest realm="API Realm", domain="/default-api", nonce="pOxqalJKm5L5QXiphgFNmrtaJsh+gU", algorithm=MD5, qop="auth", stale=true, Content-Type: text/html; charset=ISO-8859-1, Cache-Control: must-revalidate,no-cache,no-store, Content-Length: 311] org.apache.http.conn.BasicManagedEntity#5afa04c
Below is my code
val url = "http://restapi_url";
val post = new HttpPost(url)
//post.addHeader("Authorization","Basic QWBX3VzZXI6Q0NBQGRidHMxMjM=")
post.addHeader("Username","user_user")
post.addHeader("Password","clear pwd")
post.addHeader("APPLICATION_NAME","DO")
val fileContents = Source.fromFile("input.xml").getLines.mkString
post.setHeader("Content-type", "application/xml")
post.setEntity(new StringEntity(fileContents))
val response = (new DefaultHttpClient).execute(post)
println("Response Text = "+response.toString())
// print the response headers
println("--- HEADERS ---")
response.getAllHeaders.foreach(arg => println(arg))
Here the authorization header should be calculated like this:
httpPost.addHeader("Authorization", "Basic " + Base64.getEncoder.encodeToString("[your-username]:[your-password]".getBytes))
Instead of getUrlEncoder(), it should be getEncoder().
you can write like this, it works in my program
import java.util.Base64
httpPost.addHeader("Authorization", "Basic " + Base64.getUrlEncoder.encodeToString("[your-username]:[your-password]".getBytes))
DefaultHttpClient is deprecated. You should use BasicCredentialsProvider instead. Example code below:
val username = "your_username"
val password = "your_password"
val credentialsProvider = new BasicCredentialsProvider()
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(username, password)
)
val httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build()

How to include application/x-www-form-urlencoded HttpHeader in Akka-http 2.4.1?

I am using Akka Http 2.4.1 to post a https request to the twitter api.
According to their documentation, I need two httpheaders. Namely, Authorization and ContentType.
To quote their docs:
The request must include a Content-Type header with the value of application/x-www-form-urlencoded;charset=UTF-8.
Here is my code:
val authorization = Authorization(BasicHttpCredentials(key, secret))
/*
This header is removed from the request with the following explanation!
"Explicitly set HTTP header 'Content-Type: application/x-www-form-urlencoded;' is ignored, illegal RawHeader"
*/
val contentType = RawHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
Http().singleRequest(
HttpRequest(
uri = Uri("https://api.twitter.com/oauth2/token"),
method = HttpMethods.POST,
headers = List(authorization, contentType),
entity = HttpEntity(`text/plain(UTF-8)`, "grant_type=client_credentials"),
protocol = HttpProtocols.`HTTP/1.1`))
How can I include the Content-Type header with the value application/x-www-form-urlencoded;charset=UTF-8 using Akka-http 2.4.1?
I think if you change the entity value on your HttpRequest to FormData like so:
HttpRequest(
uri = Uri("https://api.twitter.com/oauth2/token"),
method = HttpMethods.POST,
headers = List(authorization),
entity = FormData("grant_type" -> "client_credentials").toEntity,
protocol = HttpProtocols.`HTTP/1.1`)
)
Then you should get the Content-Type to be automatically set for you to application/x-www-form-urlencoded;charset=UTF-8