Kamon broadcast Context is not reading HTTP headers - scala

I want to configure kamon to inspect each request and store a header value in the context in order to get access to this context from anywhere in the app. I took an example from kamon docs: https://kamon.io/docs/latest/core/context/
My webapp is built with lagom and some custom play routes. This is the config for kamon context in the application.conf
kamon.context.codecs {
string-keys {
request-id = "X-Request-ID"
}
}
and this is an example of my route
case GET(p"/helloWorld") =>
action(parser.default) { request =>
val xrequestKeyID = Context.key[String]("X-Request-ID", null)
val requestID1: String = Kamon.currentContext().get(xrequestKeyID)
println(s"requestID1=$requestID1")
val headers = request.headers.toString()
println(s"Header=${headers}")
Results.Accepted
}
when making a curl with a header, Kamon is not reading the http header.
curl --location --request GET 'http://localhost:11000/helloWorld' --header 'X-Request-ID: hello'
Here is the result in the terminal.
requestID1=
Header=List((Timeout-Access,<function1>), (Remote-Address,127.0.0.1:56854), (Raw-Request-URI,/helloWorld), (Tls-Session-Info,[Session-1, SSL_NULL_WITH_NULL_NULL]), (Host,localhost:11000), (User-Agent,curl/7.58.0), (Accept,*/*), (X-Request-ID,hello))
Do you know how to use kamon context for broadcast keys?
Thank you very much!

Related

Sse stream crashed io.gatling.http.action.sse.SseInvalidContentTypeException: Server returned http response with content-type null

I am trying to set up a load test scenario with Gatling;
package mypackage
import io.gatling.core.scenario.Simulation
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration.DurationInt
class My_LoadTest extends Simulation {
val httpProtocol = http
.baseUrl("https://my-base.url")
.header("API_KEY", "my-api-key")
val scn = scenario("MyTestScenario")
.exec(
sse("mySSE").connect("/my/end-point")
.await(10.seconds)(
sse.checkMessage("data").check(regex("""event: snapshot(.*)"""))
)
)
.pause(5)
.exec(sse("Close").close)
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}
but it's continuously throwing error:
> i.g.h.a.s.SseInvalidContentTypeException: Server returned http 1 (50.00%)
response with content-type null
> Close: Client issued close order but SSE stream was already cr 1 (50.00%)
ashed: i.g.h.a.s.SseInvalidContentTypeException: Server return...
Whereas, I have already tested with CURL command (and that works fine) as;
curl 'https://my-base.url/my/end-point' \
-H 'authority: xyz’ \
-H 'accept: text/event-stream' \
-H 'API_KEY: my’-api-key \
Now, even though, Gatling claims that Gatling automatically sets Accept header to text/event-stream and Cache-Control to no-cache., but I also tried with:
val sentHeaders = Map("Content-Type" -> "text/event-stream", "API_KEY" -> "my-api-key")
val httpProtocol = http
.baseUrl("https://my-base.url")
.headers(sentHeaders)
Whatever I have tried so far, the error remains the same; Server returned http response with content-type null.
Any clue/solution/suggestion?
Check the logs. A Server Sent Event stream must have a Content-Type header of text/event-stream, see specification. It looks like your stream is malformed.

How do I upload an image to Parse Server using Kotlin/Jvm via Rest Service?

I'm creating a Kotlin/Jvm (without Android Sdk) application that interacts with a instance of a Parse Server (Back4App). Unfortunately, parse doesn't provide a Sdk implementation to use with Java/Kotlin without Android.
So I'm using the rest Api. Now I trying to upload a image from my disk into Back4App file server. In the doc there is snippet using curl. But I wasn't able to translate into a Retrofit service:
curl -X POST \
-H "X-Parse-Application-Id: 4MGgDJ0ZiQloXoSTE2I9VM6YUYIz8EwCKF4pK7zr" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: image/jpeg" \
--data-binary '#myPicture.jpg' \
https://YOUR.PARSE-SERVER.HERE/parse/files/pic.jpg
So I based my implementation in this article and other snippets from GitHub and created a retrofit service for it:
#Multipart
#POST("/parse/files")
fun upload(
#Part file: MultipartBody.Part
): Call<ResponseBody>
And call:
var file = File("assets/escudo.png")
var requestFile = RequestBody.create(MediaType.parse("**/image"), file)
var body = MultipartBody.Part.createFormData("picture", file.name, requestFile)
var r = getService().upload(body).execute()
I created the retrofit instance as below:
fun getService(): ParserService {
val retrofit = Retrofit
.Builder()
.baseUrl("https://parseapi.back4app.com")
.addConverterFactory(GsonConverterFactory.create())
.client(createClient()).build()
return retrofit.create(ParserService::class.java)
}
fun createClient(): OkHttpClient {
return OkHttpClient.Builder().addInterceptor(createHeadInterceptor()).build()
}
fun createHeadInterceptor(): Interceptor {
return HeaderInterceptor()
}
class HeaderInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response =
chain.run {
val credentials = CredentialsUtils.readCredentials()
log.info { credentials }
proceed(
request().newBuilder()
// .addHeader("Content-Type", "application/json")
.addHeader("Content-Type", "image/png")
.addHeader("X-Parse-Application-Id", credentials.back4appAppId)
.addHeader("X-Parse-REST-API-Key", credentials.back4appRestApiKey)
.build()
)
}
}
I was able to use it to posting Json data (by uncommenting the content/type header). But when I tried to upload an image I receive this response:
Response{protocol=h2, code=400, message=, url=https://parseapi.back4app.com/parse/files}
More info:
-- EDIT
I tried a different approuch without Retrofit, it gives a 201 response code and gives me an objectId, but it doesn't upload the file:
val file2 = File("assets/escudo.png")
val serverUrl = "https://parseapi.back4app.com/classes/myfiles"
val url = URL(serverUrl)
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "POST"
conn.doOutput = true
val postData = file2.readBytes()
conn.addRequestProperty("Content-length", postData.size.toString())
conn.setRequestProperty("Content-Type", "image/*")
conn.setRequestProperty("X-Parse-Application-Id", credentials.back4appAppId)
conn.setRequestProperty("X-Parse-REST-API-Key", credentials.back4appRestApiKey)
val outputStream = DataOutputStream(conn.outputStream)
outputStream.write(postData)
outputStream.flush()
println(conn.responseCode)
-- EDIT
Trying now using Khttp:
val file = File("assets/foto.jpg")
val file2 = File("assets/escudo.png")
val serverUrl = "https://parseapi.back4app.com/classes/myfiles"
val files = listOf(FileLike("foto.jpg", file), FileLike("escudo.png", file2))
val response = post(serverUrl, headers = getHeaders(), files = files)
println(response)
println(response.text)
}
fun getHeaders(): Map<String, String> {
return mapOf(
"Content-Type" to "image/*",
"X-Parse-Application-Id" to credentials.back4appAppId,
"X-Parse-REST-API-Key" to credentials.back4appRestApiKey
)
}
Getting this error:
<Response [400]>
{"error":"Unexpected token - in JSON at position 0"}
If you're using Back4App, the correct Server URL is:
https://parseapi.back4app.com/files/pic.jpg

Translating curl into Matlab/Webwrite

I have the following curl command I need to sent to a web server using Matlab and webwrite using POST. My problem is that I always get a "Bad request" answer so my syntax must be wrong somehow. Does anybody have an idea how this curl command, sending the body could look like in Matlab using webwrite in a correct way ?
body=$(cat << EOF
{
"order": {
"units": "100",
"instrument": "EUR_USD",
"timeInForce": "FOK",
"type": "MARKET",
"positionFill": "DEFAULT"
}
}
EOF
)
curl \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <AUTHENTICATION TOKEN>" \
-d "$body" \
"https://api-fxtrade.oanda.com/v3/accounts/<ACCOUNT>/orders"
I have just asked a potentially similar question so this may not work first time. However I cannot test without knowing some login details so I can but hope this helps.
data_InputValues = struct ('units',100,'instrument','EUR_USD','timeInForce','FOK','type','MARKET','positionFill','DEFAULT');
MyBody = matlab.net.http.MessageBody(struct('order',data_InputValues));
MyHTTPOptions = matlab.net.http.HTTPOptions(); % use this to change the options if necessary (e.g. extend timeout)
Request = matlab.net.http.RequestMessage;
Request.Method = 'POST';
Request.Header = matlab.net.http.HeaderField('Content-Type','application/json','Authorization: Bearer',AUTHENTICATION TOKEN);
Request.Body = MyBody;
uri = matlab.net.URI('https://api-fxtrade.oanda.com/v3/accounts/<ACCOUNT>/orders');
[response a ~] = Request.send(uri,MyHTTPOptions);
The part I struggle with is generating the MyBody part (in your case this is parsing the order variable's sub-variables). If you get this to work I would be keen to know how! P.S. my question in case it helps: Matlab RESTful PUT Command - net.http - nesting body values
The correct format for the body is as follows:
body = struct('units',100,'instrument','EUR_USD','timeInForce','FOK',...
'type','MARKET','positionFill','DEFAULT');
As for the HTTP headers that you require you can specify them with weboptions when using webwrite.
The syntax for an additional header:
options = weboptions('KeyName','Name','KeyValue','Value')
Where Name and Value are the name of the header and its value respectively.
You must add the headers that you require in weboptions.
For the code you provided, the correct syntax would be as follows:
options = weboptions('MediaType','application/json',...
'KeyName','Authorization: Bearer','KeyValue','Token');
You can then perform the POST request at the URL of interest.
response = webwrite(url,body,options);

Can't able to view a transform in browser using REST in Marklogic 9?

I tried to install below Server-Side JavaScript using this documentation and saved below as rest-sjs
function insertTimestamp(context, params, content)
{
if (context.inputType.search('json') >= 0) {
var result = content.toObject();
if (context.acceptTypes) { /* read */
result.readTimestamp = fn.currentDateTime();
} else { /* write */
result.writeTimestamp = fn.currentDateTime();
}
return result;
} else {
/* Pass thru for non-JSON documents */
return content;
}
};
exports.transform = insertTimestamp;
I tried to push this using below curl cmd:
curl --anyauth --user public\admin:admin -X PUT -i --data-binary #"C:/Users/name/Desktop/rest.sjs" -H "Content-type: application/vnd.marklogic-javascript" 'http://localhost:9963/v1/config/transforms/js-example'
When I used localhost:9963 and went to /v1/config/transforms I can see:
<rapi:transforms xmlns:rapi="http://marklogic.com/rest-api">
<rapi:transform>
<rapi:name>rest-tsm</rapi:name>
<rapi:source-format>javascript</rapi:source-format>
<rapi:transform-parameters/>
<rapi:transform-source>/v1/config/transforms/rest-tsm</rapi:transform-source>
</rapi:transform>
</rapi:transforms>
But when I went though the module /v1/config/transforms/rest-tsm I am seeing an error response:
<error-response xmlns="http://marklogic.com/xdmp/error">
<status-code>406</status-code>
<status>Unacceptable Type</status>
<message-code>REST-UNACCEPTABLETYPE</message-code>
<message>
REST-UNACCEPTABLETYPE: (err:FOER0000) No acceptable content type: None of the requested types text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 can be provided
</message>
</error-response>
I can see the the module in Modules db. Which worked fine when I try to insert a document by using the transform.
Why can't I view the transform in the browser?
Unfortunately, that rest endpoint isn't very browser friendly. The required/acceptable Accept header values do not match what browsers will normally send.
When you made the GET request through your browser, it was sending the following Accept header:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept
This field contains a semicolon-separated list of representation schemes ( Content-Type metainformation values) which will be accepted in the response to this request.
Unfortunately, the v1/config/transform/{name} (GET) REST endpoint is strict in what it will accept for the Accept header and expects a specific value:
The MIME type of the data expected in the response, either application/xslt+xml or application/xquery.
If you use the example CURL command from the documentation, and customize for your transform URI, it will return the expected response.
curl --anyauth --user public\admin:admin -X GET -i \
-H "Accept: application/xquery" \
http://localhost:9963/v1/config/transforms/rest-tsm

How to get http request header info from the server side with spray RestAPI

I am new to Scala and Spray. I have written a simple REST API according to the instructions given in this blog post.
http://www.smartjava.org/content/first-steps-rest-spray-and-scala
And all are working as expected.
Now I want to modify the program to print the HTTP headers like Encoding, Language, remote-address, etc.. I would like to print all the header information (purpose is to log these information)
But I could not find a proper documentation or examples. Could anyone please help me to get this done.
If you need to extract a specific header:
optionalHeaderValueByName("Encoding") { encodingHeader =>
println(encodingHeader)
complete("hello")
}
alternatively you can access the raw request object and directly extractive the headers. Here's a custom directive that logs all the headers:
def logHeaders(): Directive0 = extract(_.request.headers).map(println)
Usage
logHeaders() {
complete("hello")
}
Here's how I got it working.
Directive:
def logHeaders(innerRoute: Route): (RequestContext => Unit) = extract(_.request.headers) { headers =>
headers.foreach(h => logger.info("header: {} = {}", h.name, h.value))
innerRoute
}
Usage:
logHeaders() {
complete("hello")
}