Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
The meros npm package is designed to handle multipart responses in a more convenient and efficient way. It is particularly useful for dealing with GraphQL multipart responses, allowing clients to process parts of the response as they arrive, rather than waiting for the entire response. This can improve performance and user experience in applications that consume streaming APIs or need to handle large, multipart responses.
Parsing GraphQL multipart responses
This code sample demonstrates how to use meros to parse a GraphQL multipart response from a fetch request. It checks if the response is of type 'multipart/mixed' and then uses meros to asynchronously iterate over each part of the response, logging the body of each part if it is JSON.
import { meros } from 'meros';
const response = await fetch('/graphql', {
body: JSON.stringify({ query }),
method: 'POST',
});
if (response.headers.get('content-type').includes('multipart/mixed')) {
const parts = await meros(response);
for await (const part of parts) {
if (part.json) {
console.log(part.body);
}
}
}
GraphQL Helix is a collection of utility functions for building your own GraphQL HTTP server. It supports multipart responses similar to meros but is more focused on the server-side handling of GraphQL requests, including features for query execution and subscription support.
This package is a transport layer for handling GraphQL subscriptions over WebSocket. While it doesn't directly deal with multipart responses, it offers a real-time data fetching capability that can be seen as an alternative approach to handling streaming data, compared to the multipart response handling in meros.
content-type
Visit /examples for more info!
// Relies on bundler/environment detection
import { meros } from 'meros';
const parts = await fetch('/api').then(meros);
// As a simple Async Generator
for await (const part of parts) {
// Do something with this part
}
// Used with rxjs streams
from(parts).subscribe((part) => {
// Do something with it
});
import { meros } from 'meros/browser';
// import { meros } from 'https://cdn.skypack.dev/meros';
const parts = await fetch('/api').then(meros);
import http from 'http';
import { meros } from 'meros/node';
const response = await new Promise((resolve) => {
const request = http.get(`http://example.com/api`, (response) => {
resolve(response);
});
request.end();
});
const parts = await meros(response);
Meros offers two flavours, both for the browser and for node; but their api's are fundamentally the same.
Note: The type
Response
is used loosely here and simply alludes to Node'sIncomingMessage
or the browser'sResponse
type.
meros(response: Response, options?: Options)
Returns: Promise<Response | AsyncGenerator<Part | Part[]>
Meros returns a promise that will resolve to an AsyncGenerator
if the response is of multipart/mixed
mime, or simply
returns the Response
if something else; helpful for middlewares. The idea here being that you run meros as a chain off
fetch.
fetch('/api').then(meros);
If the
content-type
is NOT a multipart, then meros will resolve with the response argument.Example on how to handle this case
import { meros } from 'meros'; const response = await fetch('/api'); // Assume this isnt multipart const parts = await meros(response); if (parts[Symbol.asyncIterator] < 'u') { for await (const part of parts) { // Do something with this part } } else { const data = await parts.json(); }
each Part
gives you access to:
json: boolean
~ Tells you the body
would be a JavaScript object of your defined generic T
.headers: object
~ A key-value pair of all headers discovered from this part.body: T | Fallback
~ Is the body of the part, either as a JavaScript object (noted by json
) or the base type
of the environment (Buffer | string
, for Node and Browser respectively).options.multiple: boolean
Default: false
Setting this to true
will yield once for all available parts of a chunk, rather than yielding once per part. This is
an optimization technique for technologies like GraphQL where rather than commit the payload to the store, to be
added-to in the next process-tick we can simply do that synchronously.
Warning: This will alter the behaviour and yield arrays—than yield payloads.
const chunks = await fetch('/api').then((response) => meros(response, { multiple: true }));
// As a simple Async Generator
for await (const parts of chunks) {
for (const part of parts) {
// Do something with this part, maybe aggregate?
}
}
via the
/bench
directory with Node v18.0.0
Node
✔ meros ~ 1,271,218 ops/sec ± 0.84%
✘ it-multipart ~ 700,039 ops/sec ± 0.72%
--
it-multipart (FAILED @ "should match reference patch set")
Browser
✔ meros ~ 800,941 ops/sec ± 1.06%
✘ fetch-multipart-graphql ~ 502,175 ops/sec ± 0.75%
--
fetch-multipart-graphql (FAILED @ "should match reference patch set")
Why the name? meros comes from Ancient Greek μέρος méros, meaning "part".
This library aims to implement RFC1341 in its entirety, however we aren't there yet. That being said, you may very well use this library in other scenarios like streaming in file form uploads.
Another goal here is to aide in being the defacto standard transport library to support
@defer
and @stream
GraphQL directives
/alternative
, /digest
or /parallel
subtype at this time.Special thanks to Luke Edwards for performance guidance and high level api design.
This library is simple, a meer few hundred bytes. It's easy to copy, and easy to alter. If you do, that is fine ❤️ im all for the freedom of software. But please give credit where credit is due.
MIT © Marais Rossouw
By default, we'll look for JSON, and parse that for you. If not, we'll give you the body as what was streamed. ↩
FAQs
A fast 642B utility that makes reading multipart responses simple
The npm package meros receives a total of 1,838,048 weekly downloads. As such, meros popularity was classified as popular.
We found that meros demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.