@@ -831,56 +831,6 @@ PHP_METHOD(Signalforge_Http_Request, create)
831831 RETURN_THROWS ();
832832 }
833833
834- /* Extract URI string from parameter */
835- if (Z_TYPE_P (uri_param ) == IS_STRING ) {
836- uri_str = Z_STR_P (uri_param );
837- } else if (Z_TYPE_P (uri_param ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (uri_param ), signalforge_uri_ce )) {
838- /* Uri object - convert to string */
839- signalforge_uri_object * uri_obj = Z_SIGNALFORGE_URI_P (uri_param );
840- smart_str buf = {0 };
841-
842- if (uri_obj -> scheme && ZSTR_LEN (uri_obj -> scheme ) > 0 ) {
843- smart_str_append (& buf , uri_obj -> scheme );
844- smart_str_appendl (& buf , "://" , 3 );
845- }
846- if (uri_obj -> host && ZSTR_LEN (uri_obj -> host ) > 0 ) {
847- if (uri_obj -> user && ZSTR_LEN (uri_obj -> user ) > 0 ) {
848- smart_str_append (& buf , uri_obj -> user );
849- if (uri_obj -> pass && ZSTR_LEN (uri_obj -> pass ) > 0 ) {
850- smart_str_appendc (& buf , ':' );
851- smart_str_append (& buf , uri_obj -> pass );
852- }
853- smart_str_appendc (& buf , '@' );
854- }
855- smart_str_append (& buf , uri_obj -> host );
856- if (uri_obj -> port != SIGNALFORGE_PORT_UNSET &&
857- !signalforge_is_standard_port (uri_obj -> scheme , uri_obj -> port )) {
858- smart_str_appendc (& buf , ':' );
859- smart_str_append_long (& buf , uri_obj -> port );
860- }
861- }
862- if (uri_obj -> path && ZSTR_LEN (uri_obj -> path ) > 0 ) {
863- smart_str_append (& buf , uri_obj -> path );
864- } else if (!uri_obj -> host || ZSTR_LEN (uri_obj -> host ) == 0 ) {
865- smart_str_appendc (& buf , '/' );
866- }
867- if (uri_obj -> query && ZSTR_LEN (uri_obj -> query ) > 0 ) {
868- smart_str_appendc (& buf , '?' );
869- smart_str_append (& buf , uri_obj -> query );
870- }
871- if (uri_obj -> fragment && ZSTR_LEN (uri_obj -> fragment ) > 0 ) {
872- smart_str_appendc (& buf , '#' );
873- smart_str_append (& buf , uri_obj -> fragment );
874- }
875-
876- smart_str_0 (& buf );
877- uri_str = buf .s ? buf .s : zend_empty_string ;
878- } else {
879- zend_throw_exception (spl_ce_InvalidArgumentException ,
880- "URI must be a string or Uri object" , 0 );
881- RETURN_THROWS ();
882- }
883-
884834 /* Create new instance */
885835 object_init_ex (return_value , signalforge_request_ce );
886836 intern = Z_SIGNALFORGE_REQUEST_P (return_value );
@@ -902,15 +852,37 @@ PHP_METHOD(Signalforge_Http_Request, create)
902852 ALLOC_HASHTABLE (intern -> ht_attributes );
903853 zend_hash_init (intern -> ht_attributes , 8 , NULL , ZVAL_PTR_DTOR , 0 );
904854
905- /* Set the URI */
906- ZVAL_STR_COPY (& intern -> zv_uri , uri_str );
907- intern -> request_uri = Z_STRVAL (intern -> zv_uri );
908- intern -> request_uri_len = Z_STRLEN (intern -> zv_uri );
855+ /* Set the URI - handle ownership correctly */
856+ if (Z_TYPE_P (uri_param ) == IS_STRING ) {
857+ /* Borrowed from parameter - must copy */
858+ ZVAL_STR_COPY (& intern -> zv_uri , Z_STR_P (uri_param ));
859+ } else if (Z_TYPE_P (uri_param ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (uri_param ), signalforge_uri_ce )) {
860+ /* Uri object - call __toString() and transfer ownership */
861+ zval uri_string_zv ;
862+ zend_call_method_with_0_params (Z_OBJ_P (uri_param ), Z_OBJCE_P (uri_param ),
863+ NULL , "__tostring" , & uri_string_zv );
864+
865+ if (EG (exception )) {
866+ RETURN_THROWS ();
867+ }
868+
869+ if (Z_TYPE (uri_string_zv ) != IS_STRING ) {
870+ zval_ptr_dtor (& uri_string_zv );
871+ zend_throw_exception (spl_ce_RuntimeException ,
872+ "Uri::__toString() must return a string" , 0 );
873+ RETURN_THROWS ();
874+ }
909875
910- /* Release temporary uri_str if it was created from Uri object conversion */
911- if (Z_TYPE_P (uri_param ) == IS_OBJECT && instanceof_function (Z_OBJCE_P (uri_param ), signalforge_uri_ce )) {
912- zend_string_release (uri_str );
876+ /* Transfer ownership from temporary zval to object */
877+ ZVAL_COPY_VALUE (& intern -> zv_uri , & uri_string_zv );
878+ ZVAL_UNDEF (& uri_string_zv ); /* Mark as transferred, no double-free */
879+ } else {
880+ zend_throw_exception (spl_ce_InvalidArgumentException ,
881+ "URI must be a string or Uri object" , 0 );
882+ RETURN_THROWS ();
913883 }
884+ intern -> request_uri = Z_STRVAL (intern -> zv_uri );
885+ intern -> request_uri_len = Z_STRLEN (intern -> zv_uri );
914886
915887 /* Set query string if present in URI */
916888 const char * query_pos = strchr (Z_STRVAL (intern -> zv_uri ), '?' );
0 commit comments