Complete route with source and get its materialised value - akka-stream

There's a route that goes somewhat like this:
val route =
path("data") {
get {
val src: Source[ByteString, BoundedSourceQueue[ByteString]] = ???
complete(HttpEntity(ContentTypes.`application/octet-stream`, src))
}
}
How can I access materialised value of this source?

Prematerializing src should do the trick.
// will need an implicit ActorSystem/ActorMaterializer in scope
val baseSrc: Source[ByteString, BoundedSourceQueue[ByteString]] = ???
val (bsq, src) = baseSrc.preMaterialize()
// do stuff with bsq...
complete(HttpEntity(ContentTypes.`application/octet-stream`, src))

Related

How to create a deep copy of a mutableStateList

I currently have this List of MutableStateLists:
val guessArray = List(5) { List(6) { "" }.toMutableStateList() }
I need to get a deep copy of each list by index, so something like:
var givenIndex = 0
val copiedArray = guessArray[givenIndex].//deep copy
copiedArray.forEach{} // some more code
What is the best way around this?
EDIT:
Went with this is the end:
val copyGuess = guessArray[currentRow].map { it }.toMutableList()

How to get string value from an array of string defined in json template using terraform

I am trying to create routes in Transit gateway route table using a json template. However, while fetching each string value from an array of string defined in json template, getting error as below;
Error: Incorrect attribute value type\n\n on main.tf line 90, in resource \"aws_ec2_transit_gateway_route\" \"ip_route\":\n 90: destination_cidr_block = each.value.ip_network\n |----------------\n | each.value.ip_network is tuple with 3 elements\n\nInappropriate value for attribute \"destination_cidr_block\": string require
Here below is my code -->
resource "aws_ec2_transit_gateway_route" "ip_route" {
for_each = jsondecode(file("templates/my.json"))
destination_cidr_block = each.value.ip_network
transit_gateway_attachment_id = "tgw-attach-123"
transit_gateway_route_table_id = each.value.tgw_rt_id
}
json file -->
{
"RT-1": {
"tgw_rt_id": "tgw-rtb-00128",
"ip_network": [
"1.1.1.0/24",
"1.1.2.0/24",
"1.1.3.0/24"
]
},
"RT-2": {
"tgw_rt_id": "tgw-rtb-01f1b",
"ip_network": [
"1.1.1.0/24",
"1.1.2.0/24",
"1.1.3.0/24"
]
}
}
I am able to get the "destination_cidr_block" value as "string" if only single string is passed in "ip_network" (eg: "ip_network": "1.1.1.0/24") but failed to fetch when defined with array of string.
As you've identified, the destination_cidr_block only accepts a single CIDR block (a string), not multiple CIDR blocks. You need to create a separate aws_ec2_transit_gateway_route for each CIDR block for each route table. You can do this by flattening the map so there's one element for each RT/CIDR combination.
locals {
route_tables = jsondecode(file("templates/my.json"))
rt_cidr_blocks = merge([
for k, rt in local.route_tables:
{
for i, ip_network in rt.ip_network:
"${k}-${i}" => {
tgw_rt_id = rt.tgw_rt_id
ip_network = ip_network
}
}
]...)
}
resource "aws_ec2_transit_gateway_route" "ip_route" {
for_each = local.rt_cidr_blocks
destination_cidr_block = each.value.ip_network
transit_gateway_attachment_id = each.key
transit_gateway_route_table_id = each.value.tgw_rt_id
}
If you want to see what the flattened map looks like now:
output "rt_cidr_blocks" {
value = local.rt_cidr_blocks
}
Output:
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
blocks = {
"RT-1-0" = {
"ip_network" = "1.1.1.0/24"
"tgw_rt_id" = "tgw-rtb-00128"
}
"RT-1-1" = {
"ip_network" = "1.1.2.0/24"
"tgw_rt_id" = "tgw-rtb-00128"
}
"RT-1-2" = {
"ip_network" = "1.1.3.0/24"
"tgw_rt_id" = "tgw-rtb-00128"
}
"RT-2-0" = {
"ip_network" = "1.1.1.0/24"
"tgw_rt_id" = "tgw-rtb-01f1b"
}
"RT-2-1" = {
"ip_network" = "1.1.2.0/24"
"tgw_rt_id" = "tgw-rtb-01f1b"
}
"RT-2-2" = {
"ip_network" = "1.1.3.0/24"
"tgw_rt_id" = "tgw-rtb-01f1b"
}
}

Invalid argument when passing ByteArray to javascript through Rhino

I am using Rhino to evaluate some javascript, where I simply pass a ByteArray from kotlin to a function in Javascript. I know it is in bad taste to say this but I am using the same Js file in Swift, and in .Net Core, without an issue with the line that is failing in this case.
As below, I am passing bytes, a ByteArray, to the JS function decodeByteArray(). The line that fails is the one I have marked with the comment //invalid argument
I have checked the ByteArray contents and they are as expected.
Am I doing something wrong or missing something in this?
Javascript
function decodeByteArray(buf) {
var pbf = new Pbf(buf);
return JSON.stringify(decode(pbf));
}
function Pbf(buf) {
this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf);
this.pos = 0;
this.type = 0;
this.length = this.buf.length;
setUp(this);
}
Kotlin
private fun decodePbfBytes(bytes: ByteArray?): Any? {
var jsResult: Any? = null;
var params = arrayOf(bytes)
val rhino = org.mozilla.javascript.Context.enter()
rhino.optimizationLevel = -1
rhino.languageVersion = org.mozilla.javascript.Context.VERSION_ES6
try{
val scope = rhino.initStandardObjects()
val assetManager = MyApp.sharedInstance.assets
val input = assetManager.open("pbfIndex.js") //the js file containing js code
val targetReader = InputStreamReader(input)
rhino.evaluateReader(scope, targetReader, "JavaScript", 1,null)
val obj = scope.get("decodeByteArray", scope)
if (obj is org.mozilla.javascript.Function){
jsResult = obj.call(rhino, scope, scope, params)
jsResult = org.mozilla.javascript.Context.toString(jsResult)
}
}catch (ex: Exception){
Log.e("Error", ex.localizedMessage)
}finally {
org.mozilla.javascript.Context.exit()
}
return jsResult
}
Rhino's TypedArray support is a little lacking (see https://mozilla.github.io/rhino/compat/engines.html#ES2015-built-ins-typed-arrays)
I couldn't get the constructor to take a byte[] directly, but it worked after converting to a javascript array.
I believe it will work to change new Uint8Array(buf); to new Uint8Array(Array.from(buf));
While Uint8Array.from is not implemented, Array.from is.

How to NOT delete existing translations with "react-intl-translations-manager"?

I use React-Intl in my app and it works great, but to be easier to manage new keys to translate I started using "react-intl-translations-manager".
My problem is that some of my translations are used through a notification system and the babel extractor don't recognize them because it's outside of his scan scope.
So when I run "react-intl-translations-manager" it deletes all the keys relatives to notifications and other non-scanned translations.
Here is my question: is there any method to "say" to "react-intl-translations-manager" that it's forbidden to delete those keys ?
I tried multiple solutions including whitelists and other but nothing is working.
Here is my translationRunner.js (the configuration file)
const manageTranslations = require('react-intl-translations-manager').default;
manageTranslations({
messagesDirectory: 'src/messages/',
translationsDirectory: 'src/locales/',
languages: ['en_GB', 'fr_FR']
});
There are two ways to do this. One is to use hooks and another way is to override the module where deletion of the actual code happens.
To do the same we can override the getLanguageReport module from react-intl-translations-manager/dist/getLanguageReport
getLanguageReport = require('react-intl-translations-manager/dist/getLanguageReport');
getLanguageReport.original = getLanguageReport.default
getLanguageReport.default = function(defaultMessages, languageMessages, languageWhitelist) {
data = getLanguageReport.original(defaultMessages, languageMessages, languageWhitelist)
// this whitelist ids can be read through a config file as well
whitelisted_id = ['helloworld2', 'helloworld']
deleted = data.deleted;
re_add = []
for (var i=0; i < deleted.length; ) {
if (whitelisted_id.indexOf(deleted[i].key)>=0) {
// we are removing a record so lets not increment i
removed_element = deleted.splice(i,1)[0];
data.fileOutput[removed_element.key] = removed_element.message;
} else {
i++;
}
}
return data;
}
const manageTranslations = require('react-intl-translations-manager').default;
manageTranslations({
messagesDirectory: 'build/messages/src/extracted/',
translationsDirectory: 'src/translations/locales/',
languages: ['de'] // Any translation --- don't include the default language
}
);
This method works fine and will keep the helloworld2 message even if it is not there in new code.
Hooks approach
In this we use the hook reportLanguage and override it to change the data
const manageTranslations = require('react-intl-translations-manager').default;
const writeFileSync = require('fs').writeFileSync
const stringify = require('react-intl-translations-manager/dist/stringify').default;
stringifyOpts = {
sortKeys: true,
space: 2,
trailingNewline: false,
};
manageTranslations({
messagesDirectory: 'build/messages/src/extracted/',
translationsDirectory: 'src/translations/locales/',
languages: ['de'], // Any translation --- don't include the default language
overrideCoreMethods: {
reportLanguage: function(langResults) {
data = langResults.report;
// this whitelist ids can be read through a config file as well
whitelisted_id = ['helloworld2', 'helloworld']
deleted = data.deleted;
re_add = []
for (var i=0; i < deleted.length; ) {
if (whitelisted_id.indexOf(deleted[i].key)>=0) {
// we are removing a record so lets not increment i
removed_element = deleted.splice(i,1)[0];
data.fileOutput[removed_element.key] = removed_element.message;
} else {
i++;
}
}
// original definition of reportLanguage from manageTranslations.js
// unfortunately the original core method is not exposed for us to re-use
// so we need to copy the code again
if (
!langResults.report.noTranslationFile &&
!langResults.report.noWhitelistFile
) {
// printers.printLanguageReport(langResults);
writeFileSync(
langResults.languageFilepath,
stringify(langResults.report.fileOutput, stringifyOpts)
);
writeFileSync(
langResults.whitelistFilepath,
stringify(langResults.report.whitelistOutput, stringifyOpts)
);
} else {
if (langResults.report.noTranslationFile) {
printers.printNoLanguageFile(langResults);
writeFileSync(
langResults,
stringify(langResults.report.fileOutput, stringifyOpts)
);
}
if (langResults.report.noWhitelistFile) {
printers.printNoLanguageWhitelistFile(langResults);
writeFileSync(
langResults.whitelistFilepath,
stringify([], stringifyOpts)
);
}
}
}
}
});

navigate route with querystring

Will Backbone.Router.navigate set test to true:
var test = false;
var Router = Backbone.Router.extend({
routes: {
'posts': 'showPosts'
},
showPosts: function () {
test = true;
}
});
router = new Router();
Backbone.history.start();
router.navigate('posts?foo=3', {trigger: true});
assert.ok(test);
Eg, will posts?foo=3 fragment will match the posts route by default, or do I have to set another route for that, for example: posts?*querystring?
Thank you
PS: I know there exist the backbone-query-parameters but I want to know just for backbone.
You need to add another route with that expecting parameter :
routes: {
'posts?foo=:foo' : 'showPosts',
'posts': 'showPosts'
},
showPosts: function (foo) {
if(typeof foo != 'undefined'){
// foo parameters was passed
}
test = true;
}
update
You could define the general route to return all the query string and then parse it in the handler :
routes: {
'posts': 'showPosts',
'posts?*queryString' : 'showPosts'
},
showPosts: function (queryString) {
var params = parseQueryString(queryString);
if(params.foo){
// foo parameters was passed
}
}
...
// and the function that parses the query string can be something like :
function parseQueryString(queryString){
var params = {};
if(queryString){
_.each(
_.map(decodeURI(queryString).split(/&/g),function(el,i){
var aux = el.split('='), o = {};
if(aux.length >= 1){
var val = undefined;
if(aux.length == 2)
val = aux[1];
o[aux[0]] = val;
}
return o;
}),
function(o){
_.extend(params,o);
}
);
}
return params;
}
update 2
Here's a live demo to see the code in action.
Just to complement the previous answers, instead of defining two routes that have the same callback, like:
routes: {
'posts': 'showPosts',
'posts?*querystring': 'showPosts'
}
You could have only one route to keep the code cleaner:
routes: {
'posts(?*querystring)': 'showPosts'
}
Backbone docs:
Routes can contain parameter parts, :param, which match a single URL component between slashes; and splat parts *splat, which can match any number of URL components.
If you still want to keep the functionality without the matching you can define two routes
routes: {
'posts': 'showPosts',
'posts?*querystring': 'showPosts'
}
showPosts: function(querystring) {
if (querystring) {
// here you can parse your querystring, for your case the querystring variable is
// 'foo=3'
}
//here you'll show posts according to the querystring (or lack thereof)
}
Here's another take, still using lodash (underscore). Removed the _.map, added a bit of verbosity to the variables, and stripped out the starting '?' if present:
function parseQueryString(queryString)
{
if (!_.isString(queryString))
return
queryString = queryString.substring( queryString.indexOf('?') + 1 )
var params = {}
var queryParts = decodeURI(queryString).split(/&/g)
_.each(queryParts, function(val)
{
var parts = val.split('=')
if (parts.length >= 1)
{
var val = undefined
if (parts.length == 2)
val = parts[1]
params[parts[0]] = val
}
})
return params
}
RFC 3986 "syntax for URIs" states that query parameters shold come before hash fragment.
In URIs a hashmark # introduces the optional fragment near the end of the URL. The generic RFC 3986 syntax for URIs also allows an optional query part introduced by a question mark ?. In URIs with a query and a fragment, the fragment follows the query.
I have this issue handling a redirect I am getting from the server i.e. "http://foo.com/main.html?error=errormessage#site". I would like to route on the query but can't see a way to write the backbone route expression to handle this url. For now I just route on the hash and check for a query by parsing location.search.

Resources