This is a quick gotcha if you keep getting BadRequest
without a useful error message trying to connect another container to localstack S3.
Here’s part of the error I was getting:
message: null,
code: 'BadRequest',
region: null,
time: 2020-12-02T13:41:48.630Z,
requestId: null,
extendedRequestId: undefined,
cfId: undefined,
statusCode: 400,
retryable: false,
retryDelay: 85.98033816170914
}"
If you’re getting this error, check if you’ve specified a DEFAULT_REGION
in the docker-compose.yml file.
Here’s what my docker-compose.yml looked like:
# docker-compose.ymllocalstack:
networks:
testing_net:
ipv4_address: 172.28.1.9
image: localstack/localstack:latest
environment:
- SERVICES=s3:4566
- DEFAULT_REGION=us-east-1 👈 THE CULPRIT! …
First copy the contents of this docker-compose.yml file listed in the localstack
repository into a local directory (make sure the file name is not changed).
Run up the container with docker-compose up
. This will get localstack running locally.
At the time of writing this post (Oct 2020), the S3 service is available on port 4566
(i.e. http://localhost:4566
)
Install awscli-local
from here as a wrapper around localstack. This will allow you to use awslocal
in your command line, which is very close to the aws
command usage.
awslocal s3api create-bucket --bucket business-time-nonprod --region eu-west-1# You don't need the region flag in here, but adding one doesn't…
Every time you require a file in node, these are the 5 things that take place:
Node will attempt to map the string given to require()
into a path on the file system. This path could be local to node, under nodule_modules folder, or node modules under a parent directory or any other path.
Node will then load the contents of this file into memory
Wraps the content of the file with an IIFE (I’ve discussed this IIFE in another blog post How require and module.exports in node works)
Node will then evaluate the file (for eg: using the V8…
I’ve always wondered how you always have access to require
and module.exports
in any .js
files running with node. I recently found something cool.
If you console.log
arguments
in a file, and run it with node. For eg:
// someFile.js
console.log(arguments);
We actually get arguments:
[Arguments] {
'0': {},
'1': [Function: require] {
resolve: [Function: resolve] { paths: [Function: paths] },
main: Module {
id: '.',
path: '/someFolder',
exports: {},
parent: null,
filename: '/someFolder/someFile.js',
loaded: false,
children: [],
paths: [Array]
},
extensions: [Object: null prototype] {
'.js': [Function],
'.json': [Function],
'.node': [Function]
},
cache: [Object: null prototype] {
'/someFolder/someFile.js': [Module]
}
},
'2': Module {
id: '.',
path: '/someFolder',
exports: {},
parent: null,
filename: '/someFolder/someFile.js',
loaded: false,
children: [],
paths: [
'someFolder/node_modules',
'/Users/username/node_modules',
'/Users/node_modules',
'/node_modules'
]
},
'3': '/someFolder/someFile.js', …
This is a quick tutorial on setting up a simple express service using swagger 3.0.
Here’s the Github repo if you want to jump straight into the code: https://github.com/nkhil/swagger-3-setup.
Note: If you’d like to know why creating API definitions might be a good idea, this is a good read.
The biggest advantage of Swagger 3.0 that I’ve discovered are:
Let’s say our service has a GET route called /healthcheck/ready
that we call to determine the readiness of the service.
We don’t want just anyone calling this route, and so we require an authorization token in the header. Swagger lets us automagically check for authorization in the headers, and throw a 400 (malformed request) without writing any additional code. …
Here’s the array we’re starting off with:
We now want to group this array. We can do this by artist, or by year.
Group by year
Group by artist
Our groupBy
function is a curried function that makes use of partial application to help keep this function re-usable.
The groupBy
function takes a key (eg: 'year') as its only argument, and returns another function group
, which in turn takes the array of objects that we'd like to sort.
Within the group
function, we're reducing the array using an empty object as the accumulator (because that's the shape of the final result we're after). …
This is a unit test example to confirm that a particular function is called with the right parameters.
In the code above, we have two functions calculateTotal
and updateTotal
. To test that they work correctly for a given input, we’re going to test that the databaseUpdater
function is called with the correct parameters.
Proxyquire is a package that lets you stub modules that you require into your code.
Here’s a quick example of how you can use proxyquire
const databaseUpdaterSpy = sinon.spy();
const stub = {
'../model/databaseUpdater': databaseUpdaterSpy,
};
Here, I’m using chai
as the assertion library, sinon
to create spies and proxyquire
to stub the external databaseUpdater
module. …
The word closures make it sound complicated. You almost certainly understand closures already — let’s take a look at some examples.
function outer() {
const a = 23;
function inner() {
console.log(a);
}
inner();
}outer();
//=> 23// The `inner` function is said to have closure over the variable `a`
In the above example, the inner
function has access to the variable a
, and hence inner
is said to have closure over the variable a.
We can take advantage of closures to effectively hide things we might not want to expose to the public using our program.
Here’s an (impractical) example that demonstrates…
Hoisting
is maybe not the best word to describe what’s going on, since it conjures up images of tiny cranes pulling variables out of your code to the top, but here’s a quick article on what hoisting means.
When the V8 engine (the thing that reads and compiles your javaScript code into C++) parses any javaScript file, you might already know it processes it from top to bottom, line by line.
But before that, V8 does a quick scan of the file to look for any variable and function declarations. Eg:
const a = 23;function greet(){
console.log("Hello");
}
In the code above, before the file has been executed, V8 knows that a
is a constant, and a function called greet
exists. …
Sometimes, when designing for interfaces, there’s just way too much content (for the given context) to display on a particular screen. Often, the user might not need to see all the information right away. I’ve run into this issue a few times, mostly while making cards out of some data coming from a database or an API endpoint.
slice()
const string = "In an age when nature and magic rule the world, there is an extraordinary legend: the story of a warrior who communicates with animals, who fights sorcery and the unnatural. His name is Dar, last of his tribe. …