Nova postagem

検索

Pergunta
· Fev. 24

Reading HTTP multipart/form messages from EnsLib.HTTP.GenericMessage object.

Hello everyone!

I have set up an EnsLib.REST.GenericService with an  EnsLib.HTTP.InboundAdapter which forwards the http requests received by a web app to my Business Process. 

I would like to parse HTTP multipart/form messages I am receving and be able to iterate over the various fields within the request body, accessing its content type and the content itself.

As far as I understand I should use the %Net.MIMEReader class which should return a list of %Net.MIMEPart, one for each field within the request. However if I do : 

Set mimeReader = ##class(%Net.MIMEReader).%New()
Set sc = mimeReader.OpenStream(pRequest.Stream)
Set sc = mimeReader.ReadMIMEMessage(.message)
Set parts = message.Parts.Count()

 

it results that the number of Parts is zero, Even though I am sending a request with postman containing two fields. This is how it looks like:

POST ....
Host: localhost:1888
Content-Length: 290
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="first field"
Content-Type: text/plain

Test text
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="third field"
Content-Type: text/plain

Test text 2
------WebKitFormBoundary7MA4YWxkTrZu0gW--

If anyone as any clue on how to handle this case suggestions will be much appreciated!

4 Comments
Discussão (4)1
Entre ou crie uma conta para continuar
Resumo
· Fev. 24

Publicações Desenvolvedores InterSystems, Fevereiro 17 - 23, 2025, Resumo

Resumo
· Fev. 24

InterSystems Developers Publications, Week February 17 - 23, 2025, Digest

Articles
#InterSystems IRIS
#Other
#InterSystems IRIS for Health
#Developer Community Official
Announcements
Questions
February 17 - 23, 2025Week at a GlanceInterSystems Developer Community
Artigo
· Fev. 24 4min de leitura

Introducing UDP Adapter

Hello

This article follows up on the question I had asked the community UDP Adapter not working

In this article, I will present to you
1) What is "UDP"?
2) The current state of Iris with UDP
3) My solution with the UDP adapter



1) What is "UDP"?

UDP stands for User Datagram Protocol. It is one of the core protocols of the Internet Protocol (IP) suite, used for transmitting data over a network. Here are some key features of UDP:

  1. Connectionless: UDP does not establish a connection before sending data, which means it can send messages (datagrams) without prior handshaking.
  2. Unreliable: There is no guarantee that messages sent via UDP will arrive at their destination. There is no error recovery or retransmission of lost packets.
  3. Speed: Because it is connectionless and does not require error checking or correction, UDP is generally faster than TCP (Transmission Control Protocol), making it suitable for applications where speed is critical.
  4. Datagram-oriented: UDP sends messages as discrete packets, which can be of varying lengths. Each packet is treated independently.
  5. Use Cases: UDP is commonly used in applications where speed is more critical than reliability, such as video streaming, online gaming, voice over IP (VoIP), and real-time communications.

Overall, UDP is a lightweight protocol that is useful for specific applications where low latency is essential.


2) The current state of Iris with UDP

Of course, InterSystems Iris allows to use this protocol to send and receive data.
As REST protocol, there are two ways to do it :
- with the ##class(%Net.UDP).%New().
- with the EnsLib.UDP.OutboundAdapter and EnsLib.UDP.InboundAdapter

 

##class(%Net.UDP).%New()

Even if the documentation of the class is very complete, here is the link of the InterSystems documentation on how to use it.

To send/receive data with it, we use an instance of class(%Net.UDP).%New() and some method linked to it.
In summary, to send data (on localhost with port 3001) :

SET client = ##class(%Net.UDP).%New()
SET addrbin = ##class(%Net.UDP).GetHostAddr("127.0.0.1")
Set status = client.Send("message text", addrbin, 3001)

To receive data (on localhost with port 3001) :

Set sobj = ##class(%Net.UDP).%New(3001,"127.0.0.1")
Set data = sobj.Recv()

 

EnsLib.UDP.OutboundAdapter and EnsLib.UDP.InboundAdapter

This one is simpler : it is an adapter.
Here the documentation : EnsLib.UDP.OutboundAdapter et EnsLib.UDP.InboundAdapter
To send data :

Set status = ..Adapter.SendStream(stream)

To receive data :

Set status = ..Adapter.Receive(stream)


However, it doesn't work. I asked the community with my issue "UDP Adapter not working" and created a ticket to the WRC.
They replied this :

The underlying executable has not been installed anymore in the product since Ensemble 2018.1.

I checked internally and JIRA DP-437486 was submitted to update those adapters to use the %Net.UDP class, but this will be subject to product management approval and available development resources.

Unfortunately, the only option right now is to create your own custom adapter using the %Net.UDP class.

The two main differences between the class(%Net.UDP) and the EnsLib.UDP.OutboundAdapter  are

  • The %Net.UDP class uses the $System.UDP system class, so it uses Cache/IRIS kernel code to send/receive the UDP messages, while the UDP Adapter uses a command pipe to call external executables to send/receive the UDP message.
  • The %Net.UDP class sends/reads a string while the UDP adapter uses a stream to send/read messages.

 

3) My solution with the UDP adapter

So, I wrote my own (approved by the support) to send data :
 

/// Adapter to send data with UDP Connection
Class USER.UDP.OutboundAdapter Extends Ens.Adapter
{

/// Host of the UDP server
Property Host As %String [ Required ];
/// Port of the UDP server
Property Port As %Integer [ Required ];
/// if 1, show the text that will be sent
Property UDPTrace As %Integer(VALUELIST = ",0,1") [ InitialExpression = 0, Required ];
Parameter SETTINGS = "Host:Basic,Port:Basic,UDPTrace:Basic";
/// Send "text" throught the UDP connection
Method SendDataText(text As %String) As %Status
{
    Try {
        Set status = $$$OK
        If ..UDPTrace=1
        {
            Do ..ShowText(text)
        }
        
        Set udpClient = ##class(%Net.UDP).%New()
        Set addrbin = ##class(%Net.UDP).GetHostAddr(..Host)

        Set sentBytes = udpClient.Send(text, addrbin, ..Port)
    }
    Catch exception {
        Set status = exception.AsStatus()
    }    
    Return status
}

/// Convert "stream" into text and send it throught the UDP connection
Method SendDataStream(stream As %Stream.Object) As %Status
{
    Try {
        Do stream.Rewind()
        Set text = ""
        While 'stream.AtEnd{
            Set text = text _ stream.Read()
        }

        Set status = ..SendDataText(text)
    }
    Catch exception {
        Set status = exception.AsStatus()
    }    
    Return status
}

/// Convert "object" into json and send it throught the UDP connection
Method SendDataJSONObject(object As %RegisteredObject, format As %String = "iw") As %Status
{
    Try {
        Set status = ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,object,,,,format)
        $$$ThrowOnError(status)
        
        Set status = ..SendDataStream(stream)
    }
    Catch exception {
        Set status = exception.AsStatus()
    }    
    Return status
}

/// Takes a text as input,
/// Displays the traces of the associated object
Method ShowText(text As %String)
{
    Set nbParty = $SYSTEM.SQL.CEILING($LENGTH(text)/1100)
    For ii=1:1:nbParty
    {
        $$$TRACE($EXTRACT(text,ii,ii+1100))
    }
}

}

 

I hope this article was, if not helpful, interesting.


I haven't tested the EnsLib.UDP.InboundAdapter, so feel free to add more informations in the discussion.

Corentin

3 Comments
Discussão (3)0
Entre ou crie uma conta para continuar
Anúncio
· Fev. 24

[Sorteo] ¡Ayúdanos a mejorar la búsqueda en DC y conviértete en un afortunado ganador!

¡Hola Comunidad!

Como nuestro último sorteo fue tan divertido, hemos decidido repetirlo 😉 Y esta vez, el tema de nuestro sorteo es 

🔎 Búsqueda en DC 🔍

Creemos que podrías tener algunas sugerencias sobre cómo podemos mejorar nuestro motor de búsqueda, ¡y nos encantaría que nos las hicieras llegar!

Como valoramos vuestro tiempo y esfuerzo, daremos un bonito premio a un miembro al azar de la Comunidad de Desarrolladores que comparta su idea sobre cómo mejorar nuestra búsqueda. Para participar en este sorteo, tienes que seguir las siguientes pautas:

  • ser miembro de la Comunidad (¡los empleados de InterSystems son bienvenidos a participar!)
  • enviar tu idea de mejora de la búsqueda al Portal de Ideas de InterSystems, elegir una categoría Comunidad, y dar una descripción lo más completa posible de lo que quieres mejorar y cómo debería hacerse
  • compartir el enlace y el nombre de tu idea en los comentarios de abajo para que otros la conozcan

¡Y ya está! A mediados de marzo, utilizaremos random.org para elegir a un afortunado propietario de nuestro bonito regalo entre todos los que hayan presentado una idea en el Portal de Ideas (y hayan seguido las directrices).

¡Mucha suerte! ☘


Notas:

  • No se aceptarán ideas duplicadas. Asegúrate de que tu propuesta es única.
  • Nos reservamos el derecho a moderar las ideas; la decisión de los moderadores es inapelable.
  • Aquí tienes una breve guía sobre cómo enviar una idea.
  • Pst, cuantas más ideas envíes, más posibilidades tendrás de conseguir un premio 🤗
Discussão (0)1
Entre ou crie uma conta para continuar