Quarkus RestEasy reactive InputStream response using wrong writer - response

I tried to optimize a reactive endpoint streaming input of an audio file based on Quarkus REST Score Console. I replaced generic Response with Reactive RestResponse. It increased the score to 100 but it is using ServerStringMessageBodyHandler instead of ServerInputStreamMessageBodyHandler now. Is there a way to tell Quarkus what MessageBodyHandler to use? Now it is calling .toString() method on inputStream object. I tried to return directly ByteArray, but the issue is the same. Any idea what is going on wrong here?
#GET
#Path("/{lectureId}/stream")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
fun getLectureStreamById(
#RestHeader("Range") rangeParam: String?,
#RestPath lectureId: LectureId
): Uni<RestResponse<InputStream>> {
return lectureAudioService.getAudioFile(lectureId).map { lectureStream ->
downloadResponse(ByteArrayInputStream(lectureStream.data), filename = "$lectureId.mp3").build()
}
}
fun downloadResponse(
data: InputStream,
filename: String,
): ResponseBuilder<InputStream> {
return ResponseBuilder.ok(data)
.header("Content-Disposition", "attachment;filename=$filename")
}

Based on answer in github issue it should be fixed in upcoming releases but original approach was not good as well because it blocked event loop. Better approach will be:
#Path("/{filename}/async-file")
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
fun getAsyncFile(filename: String): Uni<RestResponse<AsyncFile>> {
return Uni.createFrom().emitter { emitter: UniEmitter<in RestResponse<AsyncFile>> ->
vertx.fileSystem().open(
"$filename.mp3", OpenOptions()
) { result: AsyncResult<AsyncFile> ->
if (result.succeeded()) emitter.complete(
ResponseBuilder.ok(result.result()).header("Content-Disposition", "attachment;filename=$filename.mp3").build()
) else emitter.fail(result.cause())
}
}
}
Thanks to #geoand

Related

How can I receive data by POST in Hyper?

What I want to do is really what the title says. I would like to know how I can receive data per post in hyper, for example, suppose I execute the following command (with a server in hyper running on port :8000):
curl -X POST -F "field=#/path/to/file.txt" -F "tool=curl" -F "other-file=#/path/to/other.jpg" http://localhost:8000
Now, I'm going to take parf of the code on the main page of hyper as an example:
use std::{convert::Infallible, net::SocketAddr};
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
async fn handle(_: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new("Hello, World!".into()))
}
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 8000));
let make_svc = make_service_fn(|_conn| async {
Ok::<_, Infallible>(service_fn(handle))
});
let server = Server::bind(&addr).serve(make_svc);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
So, now, with this basic code, how can I receive the data per post that my curl command above would send? How do I adapt my code to read the data? I've tried to search the internet, but what I found was that hyper doesn't actually split the request body depending on the HTTP method, it's all part of the same body. But I haven't been able to find a way to process data like the above with code like mine. Thanks in advance.
Edit
I tried the exact code that they left me in the answer. That is, this code:
async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
let mut files = multipart::server::Multipart::from(req);
.....
}
But I get this error:
expected struct multipart::server::Multipart, found struct
hyper::Request
How can I solve that?
It is a single body, but the data is encoded in a way that contains the multiple files.
This is called multipart, and in order to parse the body correctly you need a multipart library such as https://crates.io/crates/multipart
To hyper integration you need to add the feature flag hyper in Cargo.toml
multipart = { version = "*", features = ["hyper"] }
Then
async fn handle(mut files: multipart::server::Multipart) -> Result<Response<Body>, Infallible> {
files.foreach_entry(|field| {
// contains name, filename, type ..
println!("Info: {:?}",field.headers);
// contains data
let mut bytes:Vec<u8> = Vec::new();
field.data.read_to_end(&mut bytes);
});
Ok(Response::new("Received the files!".into()))
}
You can also use it like this
async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
let mut files = multipart::server::Multipart::from(req);
.....
}

AsyncImage not loading : Coil-Jetpack Compose

I have a Jetpack Compose app that makes a call to the Picsum API (endpoint: https://picsum.photos/v2/list) and tries to display them in a LazyList using the Coil library (2.1.0). I have the typical Retrofit2 + OkHttp3 setup, and am able to get all the necessary data, including the required image URL, from the endpoint. So far so good.
However, despite having valid image URLs, I am not able to display the image in the view. I've tried both AsyncImage and Image with rememberAsyncImagePainter but to no avail. I even tried hard-coding the URL string, but it still doesn't display anything. I don't know what I'm doing wrong!
Similar posts mention the INTERNET permission, but I already have it in my AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Here is the link to my github project, and below are snippets of relevant code:
PhotoCard.kt
#Composable
fun PhotoCard(photo: Photo, ... ) {
...
Image(
painter = rememberAsyncImagePainter(photo.url),
...
)
}
PhotoListViewModel.kt
class PhotoListViewModel #Inject constructor(
private val getPhotoListUseCase: GetPhotoListUseCase
) : ViewModel() {
private val _pageState = MutableStateFlow(PageState<Photo>())
val pageState = _pageState.asStateFlow()
fun loadPhotoList(loadNextPage: Boolean = false) {
...
getPhotoListUseCase.invoke().let { response ->
if (response == null) {
...
} else {
_pageState.update {
it.copy(data = response, isInflight = false)
}
}
}
}
}
PhotoListRepository.kt
interface PhotoListRepository {
suspend fun getPhotoList(): List<Photo>?
}
PhotoListApi.kt
interface PhotoListApi {
#GET("v2/list")
suspend fun getPhotoList(): List<Photo>?
}
Photo.kt
data class Photo(
val id: String,
val author: String,
val width: Int,
val height: Int,
val url: String,
val download_url: String
)
As I see in the API url is not the direct image link. It is basically the page url of the image.
Use photo.download_url instead of photo.url

SvelteKit Node streams are no longer supported

Since node-fetch was replaced by undici in #5117 some of us encountered the error
Node streams are no longer supported — use a ReadableStream instead
like in this post
It is not easy to reproduce, for me the error occured only in production.
This is a self-answered question in case you have the same problem.
The error comes from src/runtime/server/utils.js L46 and is thrown after checking the _readableState property and some type on the response body of the request.
For me the problem was that my endpoint.ts was returning the fetch directly.
export async function post({request}){
return fetch('...')
}
This used to work but not anymore since the fetch response is a complex object with the _readableState property. To fix this you have to consume the response and return a simpler object like
export async function post({request}){
try {
const res = await fetch('...')
const data = await res.json()
return {
status: 200,
body: JSON.stringify({...data}),
}
catch(error){
return { status: 500}
}
}

Swift variable to choose struct

new approach to ask my question. I thought it was clear but apparently
not. :-D 2nd chance.
I use SWXMLhash to get information from websites. For each website i need a different struct, because the datastructure of each website is different.
I have a good working function (using 1 website as source) which i would like to transform to a general function depending on the chosen website.
The best solution i have got so far (see code below) got me a compile error on:
TorrentProviderItem = try xmlTorrent["rss"]["channel"]["item"].value()
compile error = Ambiguous reference to member 'subscript'
code of function:
private func setResultsToEqualData(result: String, Torrentprovider: TorrentProviders) {
var TorrentProviderItem: [XMLIndexerDeserializable]
var xmlTorrent: XMLIndexer!
xmlTorrent = SWXMLHash.parse(result)
switch Torrentprovider {
case .ExtraTorrent:
TorrentProviderItem = [ExtraTorrentItem]()
default:
TorrentProviderItem = [Torrentz2Item]()
}
do {
TorrentProviderItem = try xmlTorrent["rss"]["channel"]["item"].value()
} catch {
print("FOUT in torrent!!")
return
}
selectBestResult()
}
I have no clue how to fix this. Anyone else?
ps in the original function for 1 website i use:
var TorrentProviderItem: [ExtraTorrentItem]
and without the switch, that works fine.
Some showed me the options of a function within a struct. So i used this to build a workaround. I wrote a function in each struct for each website, the returning value of each function is of the same datatype.
For me it is a workaround and not the solution. I still have to add every website to the function (see below).
private func setResultsToEqualData(result: String, Torrentprovider: TorrentProviders) -> torrentProviderItem? {
var TorrentProviderItem = [torrentProviderItem]()
var xmlTorrent: XMLIndexer!
xmlTorrent = SWXMLHash.parse(result)
switch Torrentprovider {
case .ExtraTorrent:
var tempExtraTorrentItem: [ExtraTorrentItem]
do {
tempExtraTorrentItem = try xmlTorrent["rss"]["channel"]["item"].value()
for item in tempExtraTorrentItem {
TorrentProviderItem.append(item.result())
}
} catch {
print("FOUT in torrent!!")
return nil
}
case .Torrentz2:
var tempTorrentz2Item: [Torrentz2Item]
do {
tempTorrentz2Item = try xmlTorrent["rss"]["channel"]["item"].value()
for item in tempTorrentz2Item {
TorrentProviderItem.append(item.result())
}
} catch {
print("FOUT in torrent!!")
return nil
}
}
return (selectBestResult(results: TorrentProviderItem))
}
I think the solution to create a general function lay's within the Strucs. To use one struct for all websites in stead of a struct for each website. I just don't know how to do this. Jet.

Block JS with Firefox Addon

im developing a little firefox addon with the addon-sdk provided by mozilla. The addon should work on only one specific website and it needs to block a js-file from this website. I'm searching for hours on how to block such a request.
Hopefully someone knows the answer
Yeah, you'd have to do this mostly by hand. The SDK isn't going to help you much at all here but it is somewhat possible.
This is along the lines of what you'd need to do. Note that this isn't tested and won't work out of the box but just to give you an idea of what components are involved and where to find more resources.
const { Cc, Ci, Cm, components } = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
const CategoryManager = Cc["#mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
function PolicyComponent() { }
PolicyComponent.prototype = {
desc: "My nsIContentPolicy XPCOM Component",
classID: components.ID("{3ffd2f60-3784-11e1-b86c-0800200c9a66}"),
contractID: "#abc.def.com/policycomp;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]),
shouldLoad: function(contentType, contentLocation, requestOrigin, aContext, mimeTypeGuess, extra) {
if (contentLocation.spec != BLOCKED_JS) { return return Ci.nsIContentPolicy.ACCEPT; }
else { return Ci.nsIContentPolicy.REJECT_REQUEST; }
},
shouldProcess: function() {
return CI.nsIContentPolicy.ACCEPT;
}
}
var pc = new PolicyComponent()
// Register the Interface
Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(pc.uuid, pc.desc, pc.contractID, pc);
// Add the content policy
CategoryManager.addCategoryEntry("content-policy",pc.className,pc.contractID, true, true); // not sure you should replace (last true statement)
See this post for more:
What is missing in my nsIContentPolicy Firefox/IceWeasel extension XPCOMponent implementation for the shouldLoad to be called?
Also take a look at these docs: https://developer.mozilla.org/en/XUL_School/Intercepting_Page_Loads#Content_Policy

Resources