How do you define a file response as a Message - protocol-buffers

I'm using proto to define a REST service
In my service, I'm trying to document that a service responds with a file.
I've looked through here https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf but couldn't find anything that looked like a file.
service SomeService {
rpc GetStaticAsset(GetMessageRequest) returns (FileAsset) {
option (google.api.http) = {
get: "/static/{assetName}"
};
}
}
message FileAsset {
¯\_(ツ)_/¯
}

Found the answer here:
message Chunk {
bytes Content = 1;
}

Related

kitex "could not import echoTest/kitex_gen/echo"

when I use kitex to start an examples, I Got an error like below
for my step:
mkdir -p Protobuf-test
new file whose name is "echo.proto" and content is like this
syntax = "proto3";
option go_package = "echo";
package echo;
message Request {
string msg = 1;
}
message Response {
string msg = 1;
}
service EchoService {
rpc ClientSideStreaming(stream Request) returns (Response){} // 客户端streaming
rpc ServerSideStreaming(Request) returns (stream Response){} // 服务端streaming
rpc BidiSideStreaming(stream Request) returns (stream Response){} //双向流
}
open a terminal executed a command
kitex -type protobuf -module echoTest -service echoTest echo.proto
please give me some advise, thanks very mush
I take a comparison to using "thrift", it is ok, in the directory "xx/kitex_gen/echo", there has a file named echo.go, but not when using protobuf as model

MassTransit endpoint name is ignored in ConsumerDefinition

The EndpointName property in a ConsumerDefinition file seems to be ignored by MassTransit. I know the ConsumerDefinition is being used because the retry logic works. How do I get different commands to go to a different queue? It seems that I can get them all to go through one central queue but I don't think this is best practice for commands.
Here is my app configuration that executes on startup when creating the MassTransit bus.
Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
cfg.Host(_config.ServiceBusUri, host => {
host.SharedAccessSignature(s =>
{
s.KeyName = _config.KeyName;
s.SharedAccessKey = _config.SharedAccessKey;
s.TokenTimeToLive = TimeSpan.FromDays(1);
s.TokenScope = TokenScope.Namespace;
});
});
cfg.ReceiveEndpoint("publish", ec =>
{
// this is done to register all consumers in the assembly and to use their definition files
ec.ConfigureConsumers(provider);
});
And my handler definition in the consumer (an azure worker service)
public class CreateAccessPointCommandHandlerDef : ConsumerDefinition<CreateAccessPointCommandHandler>
{
public CreateAccessPointCommandHandlerDef()
{
EndpointName = "specific";
ConcurrentMessageLimit = 4;
}
protected override void ConfigureConsumer(
IReceiveEndpointConfigurator endpointConfigurator,
IConsumerConfigurator<CreateAccessPointCommandHandler> consumerConfigurator
)
{
endpointConfigurator.UseMessageRetry(r =>
{
r.Immediate(2);
});
}
}
In my app that is sending the message I have to configure it to send to the "publish" queue, not "specific".
EndpointConvention.Map<CreateAccessPointsCommand>(new Uri($"queue:specific")); // does not work
EndpointConvention.Map<CreateAccessPointsCommand>(new Uri($"queue:publish")); // this does work
Because you are configuring the receive endpoint yourself, and giving it the name publish, that's the receive endpoint.
To configure the endpoints using the definitions, use:
cfg.ConfigureEndpoints(provider);
This will use the definitions that were registered in the container to configure the receive endpoints, using the consumer endpoint name defined.
This is also explained in the documentation.

Geocoding requests to HERE API randomly fails

I am trying to geocode addresses with HERE API. I am not free plan. I try following code (Spring Boot in Kotlin):
override fun geocode(address: Address): Coordinate? {
val uriString = UriComponentsBuilder
.fromHttpUrl(endpoint)
.queryParam("app_id", appId)
.queryParam("app_code", appCode)
.queryParam("searchtext", addressToSearchText(address))
.toUriString()
logger.info("Geocode requested with url {}", uriString)
val response = restTemplate.getForEntity(uriString, String::class.java)
return response.body?.let {
Klaxon().parse<GeocodeResponse>(it)
}?.let {
it.Response.View.firstOrNull()?.Result?.firstOrNull()
}?.let {
Coordinate(
latitude = it.Location.DisplayPosition.Latitude,
longitude = it.Location.DisplayPosition.Longitude
)
}.also {
if (it == null) {
logger.warn("Geocode failed: {}", response.body)
}
}
}
It turned out that when I call this method many times in a row, some requests returns empty responses, like this:
{
"Response":{
"MetaInfo":{
"Timestamp":"2019-04-18T11:33:17.756+0000"
},
"View":[
]
}
}
I could not figure out any rule why some requests fail. It seems to be just random.
However, when I try to call same URLs with curl of in my browser, everything works just fine.
I guess there is some limit for amount requests per seconds, but I could not find anything in HERE documentation.
Does anyone have an idea about the limit? Or may it be something else?
Actually, there was a problem with my code. Requests were failing for addresses having "special" symbols like ü and ö. The problem was with building request URL
val uriString = UriComponentsBuilder
.fromHttpUrl(endpoint)
.queryParam("app_id", appId)
.queryParam("app_code", appCode)
.queryParam("searchtext", addressQueryParam(address))
.build(false) // <= this was missed
.toUriString()

Provider pactVerify isn't picking up JSON Pact file

I have two projects in the same repo, with completely separate directory structures (consumer in /test-consumer, provider in /app).
The consumer check outputs a JSON Pact file in /test-consumer/build/pacts, as expected by
dependencies { test { systemProperties['pact.rootDir'] = "$buildDir/pacts" } }
I then copy the file into /app/build/pacts/, and put this same systemProperties line into my provider's build.gradle.
The sample project that I'm plagiarising from is using a Pact broker, so I guessed I can take that out, and replace it with the rootDir, but it's not working. This is what I get:
WARNING: There are no consumers to verify for provider 'Coffee Ordering Provider'
So, it seems like it's finding the Pact files, but can't find a provider+consumer pair in any of them.
TL;DR:
What am I doing wrong?
Here are some code bits to help:
dependencies {
...
test { systemProperties['pact.rootDir'] = "$buildDir/pacts" }
}
pact {
serviceProviders {
'Coffee Ordering Provider' {
port = 8080
startProviderTask = startProvider
terminateProviderTask = stopProvider
stateChangeUrl = url('http://localhost:8080/pactStateChange')
}
}
}
You are getting that warning because you have not told the pact plugin where to find the pact files. For pacts in a directory, add the following:
pact {
serviceProviders {
'Coffee Ordering Provider' {
port = 8080
startProviderTask = startProvider
terminateProviderTask = stopProvider
stateChangeUrl = url('http://localhost:8080/pactStateChange')
hasPactsWith('Coffee Ordering Consumers') {
// Will define a consumer for each pact file in the directory.
// Consumer name is read from contents of pact file
pactFileLocation = file("$buildDir/pacts")
}
}
}
}
Just a note that you were setting the pact.rootDir for all tests, but the pact verification does not run as a test.

Can Websocket and normal get route be same in Akka Http?

I do have a scenario where I will want my websocket route and get route paths to be the same. Is it possible in Akka Http?
Consider the below mentioned code:
def flow: Flow[Message, Message, Any] =
Flow.fromSinkAndSource(Sink.ignore,
Source.single(TextMessage.Strict("Hello from websocket")))
val route =
path("hello") {
get {
complete(HttpEntity(ContentTypes.`application/json`,"Simple hello"))
}
} ~ path("hello") {
handleWebSocketMessages(flow)
}
If, through a websocket client, I access ws://localhost:8080/hello, I get an websocket error. But a normal curl request gives the result of Simple hello. Is it possible to somehow achieve both actions on same route.
Something along the lines of the below should do
val route = path("hello") {
optionalHeaderValueByType[UpgradeToWebSocket](()) {
case Some(upgrade) => complete(upgrade.handleMessages(flow))
case None => get {
complete("Simple hello")
}
}
}

Resources