How k6 sending files in field - k6

I reference this python send files to send file.
And this is my python frontend code. (I have a backend to receive the files["img"])
import requests
host = "http://example.org:5000"
with open("./test.png", "rb") as f:
r = requests.get(host, files={"img": f})
print(r.text)
So the structure would like this
{
"origin": ...,
"files": {
"img": "<censored...binary...data>"
},
"form": {},
"url": ...,
"args": {},
"headers": {
...
},
"data": ...
}
And I want to use k6 to testing it. I've read k6 file and write the script like this.
import http from "k6/http";
const img = open("./test.png", "b");
export default function() {
const params = {files: {"img": img}};
http.get("http://example.org:5000", params);
}
It seems that I did wrong. The request always failed. How can I fix that?

You are calling http.get which will send a GET request. To upload a file you need a POST request. You also need to wrap it in http.file. See Multipart request in the k6 documentation:
import http from 'k6/http';
const binFile = open('/path/to/file.bin', 'b');
export default function () {
const data = {
file: http.file(binFile, 'test.bin'),
};
const res = http.post('https://example.com/upload', data);
}
With your code:
import http from "k6/http";
const img = open("./test.png", "b");
export default function() {
const params = {img: http.file(img, 'test.png')};
http.post("http://example.org:5000", params);
}

Related

What is the best practice to bypass my specific dynamic code evaluation in next.js middleware?

I use next.js middleware to retrieve a data stored inside a cookie, and to check in a db (using strapi) if this specific user exists, or if he needs to register before going further.
// middleware.js
import { getToken } from 'next-auth/jwt';
import qs from 'qs';
import { MY_DB } from './constants';
export async function middleware(request) {
const token = await getToken({
req: request,
secret: process.env.SECRET,
});
const params = qs.stringify({
filters: {
address: {
$eq: token.sub,
},
},
});
const url = MY_DB + '/api/users/?' + params;
const result = await fetch(url, {
method: 'GET',
headers: { accept: 'application/json' },
});
// remaining code checks if the request is empty or not and returns the appropriate page
(...)
building my project returns the following error :
Failed to compile.
./node_modules/.pnpm/function-bind#1.1.1/node_modules/function-bind/implementation.js
Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime
Learn More: https://nextjs.org/docs/messages/edge-dynamic-code-evaluation
Import trace for requested module:
./node_modules/.pnpm/function-bind#1.1.1/node_modules/function-bind/implementation.js
./node_modules/.pnpm/function-bind#1.1.1/node_modules/function-bind/index.js
./node_modules/.pnpm/get-intrinsic#1.1.3/node_modules/get-intrinsic/index.js
./node_modules/.pnpm/side-channel#1.0.4/node_modules/side-channel/index.js
./node_modules/.pnpm/qs#6.11.0/node_modules/qs/lib/stringify.js
./node_modules/.pnpm/qs#6.11.0/node_modules/qs/lib/index.js
> Build failed because of webpack errors
 ELIFECYCLE  Command failed with exit code 1.
I highly suspect the qs.stringify call given the stacktrace, but how can I overcome this in an elegant way ?

Nextjs: How to send a custom 200 response at root when the base path is configured

I m using nextjs and have configured base path in next.config.js.
It looks something like this
const nextConfig = {
reactStrictMode: true,
output: 'standalone',
basePath: '/new',
};
So now whenever I hit http://localhost:3000/new I get the homepage.
Howevever, when I hit http://localhost:3000 without basePath, I get a 404.
What I want is to get a 200 response with some custom response like OK.
Even if I don't get the custom response text, getting 200 is required.
How to achieve that?
First do this
const nextConfig = {
reactStrictMode: true,
output: 'standalone',
basePath: '/new',
};
Just as you have done already, to the next thing you have to do is to add a middleware just at the root of the page
Then watch for the pathnames that is passed from the request
export async function middleware(req: NextRequest) {
const { nextUrl} = req;
if(nextUrl.pathname === '/'){
return NextResponse.json({hello: "world" });
}
}

Deno serve imported from std/http/server.ts is not async iterable?

Here's the entirety of my .js file:
import { serve } from "https://deno.land/std/http/server.ts"
let server = serve({ port: 4000 })
for await (const req of server){
console.log('literally anything')
}
I'm using entirely code which i've seen multiple other people run without issues, and i have myself ran similar for loops before on this same machine. I don't understand what i broke, or if i'm importing the wrong thing, i have no idea what the right thing is. I'm on Local Deno version 1.18.1, the path is the one i get from the deno.land site, and the error i get when i try deno run --allow-net on that code is:
error: Uncaught TypeError: server is not async iterable
for await (const req of server){
at file:///H:/proj/testapp/serveHTTP.js:4:25
The return type of serve used to be Server (which is async iterable) up until std version 0.106.0: here's a link to that version of serve. That's probably why you've seen examples using it that way.
Starting in version 0.107.0 of std, the signature of serve changed to accept a Handler instead (and return Promise<void>).
Here's a link to the documentation for the current version of serve (from std#0.123.0), and here's an example of how to use it:
so-70963882.ts:
import { serve } from "https://deno.land/std#0.123.0/http/server.ts";
function requestHandler (request: Request): Response {
const data = {
url: request.url,
headers: Object.fromEntries([...request.headers].sort()),
};
console.log(data);
const body: BodyInit = JSON.stringify(data, null, 2);
const headers = new Headers([['content-type', 'application/json']]);
const init: ResponseInit = {headers};
return new Response(body, init);
}
const ac = new AbortController();
serve(requestHandler, { port: 4000, signal: ac.signal });
const responseText = await (await fetch('http://localhost:4000')).text();
console.log(responseText);
ac.abort();
In the console:
deno run --allow-net ./so-70963882.ts
{
url: "http://localhost:4000/",
headers: {
accept: "*/*",
"accept-encoding": "gzip, br",
host: "localhost:4000",
"user-agent": "Deno/1.18.1"
}
}
{
"url": "http://localhost:4000/",
"headers": {
"accept": "*/*",
"accept-encoding": "gzip, br",
"host": "localhost:4000",
"user-agent": "Deno/1.18.1"
}
}
You should always use versioned URLs — which are more likely to "be immutable" (provide idempotent responses) — for imported modules whenever possible.

It's possible to get next.js request object globally?

I am using fastify with next.js and I need to include tracing (requestId is the problem so far). What I am doing right now is creating a fastify onRequest hook and generating a requestId value and setting it in request object (could be as a request header as well). What I want is to get access to this request object for two reasons:
In logger object (pino in this case, I want to include the requestId in all custom server-side logs).
In all request that needs to be made to other services need to include the requestId in headers.
Maybe I am missing something trivial and I'm not doing it the best way.
HERE SOME SNIPPETS
This how I am generating the reqId
const fastify = fastifyFactory({
logger, // logger configuration (Pino instance with custom configuration, see below)
genReqId: () => {
return Math.random()
.toString(36)
.slice(-6);
}
});
pino instance
const pino = require('pino');
const logger = pino({
messageKey: 'message',
prettyPrint: true,
changeLevelName: 'severity',
useLevelLabels: true,
base: {
serviceContext: {
service: 'web'
}
},
level:'info'
});
module.exports = {
logger
};
This is a plugin to gets the reqId generated and setting it to a query property within request object
const tracing = function tracing(fastify, opt, next) {
fastify.addHook('onRequest', (req, res, nextRequest) => {
const { id } = req;
const logger = fastify.log.child({ reqId: id });
req.query.reqId = id;
fastify.log = logger; //overrides the current fastify logger to include the reqId in all custom logs
nextRequest();
});
next();
};
tracing[Symbol.for('skip-override')] = true;
module.exports = tracing;
I have no problem when using fastify.log.info(...) because how logger is overrided in each request, it will include the reqId as a child log. The problem is that I want to create a generic logger to use at any part and fastify logger is not available in React components (for example to write logs at getInitialProps). Another important think is tha I need to include this reqId in all request I send to other services (ex: when fetching data), this is why I tried to store this value in request object but need to get it.
Starting from a project build with:
npx create-next-app --example custom-server-fastify custom-server-fastify-app
And changing the server.js with:
const Next = require('next')
const Fastify = require('fastify')
// your pino config
const fastify = Fastify({
logger: {
level: 'info',
prettyPrint: true,
changeLevelName: 'severity',
useLevelLabels: true,
base: {
serviceContext: {
service: 'web'
}
}
},
genReqId: () => { return Math.random().toString(36).slice(-6) }
})
// your plugin
const aPlugin = function yourPlugin (fastify, opts, next) {
fastify.addHook('onRequest', (request, reply, next) => {
request.log.info('hello')
const { id } = request
request.query.reqId = id
next()
})
next()
}
aPlugin[Symbol.for('skip-override')] = true
fastify.register(aPlugin)
[.... other generated code]
const port = parseInt(process.env.PORT, 10) || 3000
[.... other generated code]
fastify.get('/*', (req, reply) => {
console.log('-------->', req.id, req.query.reqId) // both your id is ok
return app.handleRequest(req.req, reply.res).then(() => {
reply.sent = true
})
[.... other generated code]
})
Then:
npm run dev
# another console
curl http://localhost:3000/
It will print out:
[1558441374784] INFO : Server listening at http://127.0.0.1:3000
serviceContext: {
"service": "web"
}
> Ready on http://localhost:3000
[1558441405416] INFO : incoming request
serviceContext: {
"service": "web"
}
reqId: "2i810l"
req: {
"method": "GET",
"url": "/",
"hostname": "localhost:3000",
"remoteAddress": "127.0.0.1",
"remotePort": 57863
}
req id ----> 2i810l
--------> 2i810l 2i810l
[ event ] build page: /
[ wait ] compiling ...
[1558441406171] INFO : request completed
serviceContext: {
"service": "web"
}
reqId: "2i810l"
res: {
"statusCode": 200
}
responseTime: 753.012099981308
So I think the misunderstanding is in the request object that is the Fastify request and not the Node.js "low level" request object, that could be accessed with request.req.
Moreover, running fastify.log = logger; is dangerous because it means that each request override and create a new logger and change the logger for the fastify instance, this is not safe, and as shown it is not necessary.
If you want more child logger (per route prefix per example) I suggest exploring/using the onRegister hook.
EDIT:
Now the custom hook print:
[1558443540483] INFO : hello
serviceContext: {
"service": "web"
}
reqId: "zjuhw2"

Meteor - Create a webhook

I'd like to implement a webhook with Meteor
I'm using the kadira/flowrouter Meteor plugin but no way to get POST data. Neither queryParams or params return the body of the message that I want to get.
FlowRouter.route('/my_weebhook', {
action: function(params, queryParams) {
console.log(queryParams);
console.log(params);
}
});
I do not know how to use kadira/flowrouter but you can use Meteor base package WebApp
to achieve what you need. Below is a sample code. You need to code or import something like this in your server.js
import { Meteor } from 'meteor/meteor';
import { WebApp } from 'meteor/webapp';
import url from "url";
WebApp.connectHandlers.use('/my_webhook', (req, res) => {
//Below two lines show how you can parse the query string from url if you need to
const urlParts = url.parse(req.url, true);
const someVar = urlParts.query.someVar;
//Below code shows how to get the request body if you need
let body = "";
req.on('data', Meteor.bindEnvironment(function (data) {
body += data;
}));
req.on('end', Meteor.bindEnvironment(function () {
//You can access complete request body data in the variable body here.
console.log("body : ", body);
//write code to save body in db or do whatever you want to do with body.
}));
//Below you send response from your webhook listener
res.writeHead(200);
res.end("OK");
});

Resources