Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PL/SQL: UTL_HTTP POST with UTF8 string results in broken characters

I want to send an UTF8 json string via utl_http to a node.js Server via POST. Sending the string

["Sant Julià de Lòria"]

does arrive as

["Sant Juli� de L�ria"]

The PL/SQL code goes like:

FUNCTION http_post_varchar(
    p_url          VARCHAR2,
    p_request_body VARCHAR2 )
  RETURN VARCHAR2
AS
  req   UTL_HTTP.REQ;
  resp  UTL_HTTP.RESP;
  value VARCHAR2(32767);  -- URL to post to
  v_url VARCHAR2(200) := p_url;
  -- Post Parameters
  v_param VARCHAR2(32767) := p_request_body;
  v_param_length NUMBER := length(v_param);
BEGIN
  req := UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => 'POST');
  UTL_HTTP.SET_HEADER (r      =>  req,
                       name   =>  'Content-Type',
                       value  =>  'application/json;charset=UTF-8');
  UTL_HTTP.SET_HEADER (r      =>   req,
                       name   =>   'Content-Length',
                       value  =>   v_param_length);
  UTL_HTTP.WRITE_TEXT (r      =>   req,
                       data   =>   v_param);

  resp := UTL_HTTP.GET_RESPONSE(req);
  LOOP
    UTL_HTTP.READ_LINE(resp, value, TRUE);    
  END LOOP;
  UTL_HTTP.END_RESPONSE(resp);
  RETURN 'OK';
EXCEPTION
  WHEN UTL_HTTP.END_OF_BODY THEN
    UTL_HTTP.END_RESPONSE(resp);
  RETURN 'OK';
END http_post_varchar;
like image 306
Federico Elles Avatar asked Feb 18 '14 11:02

Federico Elles


2 Answers

You should change your code to:

UTL_HTTP.SET_BODY_CHARSET('UTF-8');
UTL_HTTP.SET_HEADER (r      =>   req,
                     name   =>   'Content-Length',
                     value  =>    LENGTHB(v_param));

UTL_HTTP.WRITE_RAW (r    => req,
                    data => UTL_RAW.CAST_TO_RAW(v_param));

LENGTHB for byte length because of UTF-8. Otherwise the calculated length will be false and you get an error on the target side (unexpected end of input or something).

like image 170
Luscus Avatar answered Nov 20 '22 07:11

Luscus


Same goes for the response body e.g. when you're getting a response from a web service:

UTL_HTTP.SET_BODY_CHARSET(r=> resp, charset=>'UTF-8');

Place this call directly after Get_response.

like image 32
Danny Avatar answered Nov 20 '22 07:11

Danny