Do I need to free instance of TJSONArray - json

The answer is obviously yes, but I have this code that has been running for almost a month now 24/7 and everything is fine. Here is the code :
var
jsonArray : TJSONArray;
jsonValue : TJSONValue;
json : string;
begin
json := 'JSON_MASTER';
jsonArray := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(json), 0) as TJSONArray;
for jsonValue in jsonArray do
begin
// do the thing 1
end;
json := 'JSON_DETAIL';
jsonArray := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(json), 0) as TJSONArray;
for jsonValue in jsonArray do
begin
// do the thing 2
end;
end;
The application is a web service(SOAP). The function is executed around 2K per day. I am aware of the issue in the code but because the SOAP is not crushing I'm not fixing it yet. The task manager performance report shows fine. There is no sign of growing memory usage. Why is there no sign of memory leaks? Is there such thing as garbage collection in TJSONArray?

It depends on which platform you are running on.
If your app is running on a non-ARC platform, such as Windows or OSX, then YES, you need to manually free the TJSONArray when you are done using it, or else it will be leaked.
If your app is running on an ARC platform, such as iOS, Android, or Linux, then NO, you do not need to manually free the TJSONArray when you are done using it, as it will be freed automatically when all references to it have gone out of scope.

Related

Form blocked while HTTP post does not finish

I am sending JSON to an endpoint and I have a problem. The execution works, but the form gets stuck until HTTP.Post() ends, after it has finished the screen releases for use. I'm sure I'm doing something wrong.
Here is the button action that sends the JSON:
procedure TForm1.Button1Click(Sender: TObject);
var
HTTP: TIdHTTP;
vJsonAEnviar: TStringStream;
Json:String;
begin
Json := '{ '+
' "user":"Lucy"'+
' "execute":"ok"'+
' } ';
HTTP := TIdHTTP.Create;
HTTP.Request.ContentType := 'application/json';
HTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
vJsonAEnviar := TStringStream.Create(UTF8Encode(Json));
HTTP.Post('http://localhost:8080/exportaManual', vJsonAEnviar);
FreeAndNil(HTTP);
FreeAndNil(vJsonAEnviar);
end;
On the other side, it takes time to finish and the screen stays blockrd a long time.
You are not doing anything wrong (well, except for a complete lack of any error handling). This is simply how Indy is designed to operate (see Introduction to Indy). Indy uses blocking socket operations. When you perform an operation, the calling thread is blocked until the operation is complete. This is normal.
If you don't want your UI frozen while the POST is in progress, you can either:
drop a TIdAntiFreeze component onto your Form. It will pump UI messages in the background while Indy is blocking the main UI thread.
move the POST code to its own worker thread, using TThread, TTask, TIdThreadComponent, etc, and have it notify the main UI thread when finished.

IdHTTP.Get(url, ss) give 403 Forbidden

I'm using IdHTTP to execute php files on server. Worked fine for years. Suddenly getting 403 Forbidden errors with all my programs. Archived versions from year ago now fail also. Web host says they have changed nothing. To test, placed a simple php file that simply echoes a value on 3 separate host platforms (none SSL). Calls to all 3 fail with 403 error. If the url is placed in a browser address and called from there, call succeeds with expected value returned. Also tried running program connected via different ISPs. These failures just popped up in the last few days. Happens on many different computers.
Here is a very simple example that fails when sent to all 3 test servers
procedure TForm1.Button1Click(Sender: TObject);
var url: string;
H: TIdHttp;
SS: TStringStream;
begin
url := 'http://www.somesite.com/test.php';
H := TIdHttp.Create(nil);
SS := TStringStream.Create;
try
H.Get(url, SS);
Edit1.Text := SS.DataString;
finally
H.Free;
SS.Free;
end;
end;
Any help greatly appreciated.

How cookies are managed by networking code

I was recently migrating over from C# and looking to create some of my old applications. As such I have needed to find a way to manage sessions within Go web requests. I found a solution in the form of this code:
// Jar is session object struct - cookie jar including mutex for syncing
type Jar struct {
sync.Mutex
cookies map[string][]*http.Cookie
}
// NewJar is a function for creating cookie jar for use
func NewJar() *Jar {
jar := new(Jar)
jar.cookies = make(map[string][]*http.Cookie)
return jar
}
// SetCookies sets the cookies for the jar
func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
jar.Lock()
if _, ok := jar.cookies[u.Host]; ok {
for _, c := range cookies {
jar.cookies[u.Host] = append(jar.cookies[u.Host], c)
}
} else {
jar.cookies[u.Host] = cookies
}
jar.Unlock()
}
// Cookies returns cookies for each host
func (jar *Jar) Cookies(u *url.URL) []*http.Cookie {
return jar.cookies[u.Host]
}
// NewJarClient creates new client, utilising a NewJar()
func NewJarClient() *http.Client {
proxyURL, _ := url.Parse("http://127.0.0.1:8888")
tr := &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
DisableCompression: true,
Proxy: http.ProxyURL(proxyURL),
}
return &http.Client{
Jar: NewJar(),
Transport: tr,
}
}
The problem I'm having is in understanding how this works. I create a client doing the following
client := NewJarClient()
but then when I issue networking fuctions using it such as a get request, the cookies automatically carry on and it all works as planned. The problem is Ihave no idea why. I see no mention of methods such as the Cookies one or the SetCookies one ever being called and it seems to just handle each one by magically running the functions. Could someone annotate or explain the given methods line by line or in a way so that they'd make better sense to me coming over from a C# background. Thanks :)
NewJar allocates and returns a new instance of type *Jar, now type *Jar, thanks to the methods defined on it, implements the interface called CookieJar, implicitly.
The http.Client type has a field called Jar which is defined as having the type CookieJar, that means that you can set http.Client.Jar to anything that implements the CookieJar interface, including the *Jar type. The NewJarClient function returns a new *http.Client instance with it's Jar field set to the *Jar instance returned by NewJar.
This allows the returned client value to use *Jar's methods without really knowing that it's a *Jar, it only knows that the value in its Jar field has the same set of methods as those defined by the CookieJar interface.
So the http.Client instance, when sending requests, uses your *Jar by calling its methods providing the parameters and handling the returned values. How your *Jar is used by the client is an implementation detail of the http.Client type and you don't have to worry about that. You just need to make sure that the methods that implement the CookieJar interface do what you want them to do, how and when they are called is up to the client.
But if you're interested in the implementation details of the client anyway, you can check out the source file of http.Client.
Due to misinformation in the form of a few dated blog posts, I came to the impression that I was unable to maintain cookies across requests in go - for some weird reason. Having thought that, I researched and looked into creating my own implementation which ca be seen above. It's been brought to my attention that my implementation is completely broken and flawed and that the standard http library itself can perfectly handle maintaining cookies, simply by including a value for the Jar when creating a client. For example:
jar, _ := cookiejar.New(nil)
proxyURL, _ := url.Parse("http://127.0.0.1:8888")
tr := &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
DisableCompression: true,
Proxy: http.ProxyURL(proxyURL),
}
c := &http.Client{
Jar: jar,
Transport: tr,
}

Problems while parsing a json file coming from google speech server

I am trying to implement google speech recognition api into my program. To do this I use the function below to parse json file sended from google server. However program sometimes works well sometimes not and gets access violation error
The code is below. Where is problem? is there anyway to check whether the json object is true format or not before parsing it?
function TGoogleSpeech.Convert(const stream: TStream): string;
var
ret: string;
js: TlkJSONobject;
begin
try
ret := FHttp.Post(FURL, stream);
js := TlkJSON.ParseText(ret) as TlkJSONobject;
try
Result := js.Field['hypotheses'].Child[0].Field['utterance'].Value;
finally
js.Free;
end;
except
Result := '';
end;
end;
I am using the uLKJSOn library.
guys I found the answer:
And it is really interesting,
when recognition is not good Googleserver sends this code as json
{"status":5,"id":"","hypotheses":[]}
it doesn't have utterance field and that cause problem.
Therefore I did this update and clean the unwanted part using the code below
ret :=ansireplacetext(ret,'{"status":5,"id":"","hypotheses":[]}','');
if (AnsiContainsText(ret,'utterance') and (length(ret)>1) then
and so on..

How to download a file in a password-protected location in Delphi 2007

I need to get the contents of a HTML page from the Web, but the contents of the respective resource is only available after the user has logged into the website.
To be more specific, I need to download the HTML page of a video file that has been flagged as inappropriate on Youtube. I do have the login credentials, but I'm not sure on how to proceed with the login.
I'm currently downloading non-password-protected HTML pages with HTTPSend from Synapse, and I also have a licensed copy of Clever Internet Suite 7 I used in a previous project.
The code I'm using looks like that (this is strictly informative, I can change the approach if necessary):
function GetHTMLFile(s: string): string;
var
sHTTPSource:TStringList;
HTTP: THTTPSend;
begin
try
sHTTPSource := TStringList.Create;
if HttpGetText(s, sHTTPSource) then
begin
result := sHTTPSource.Text;
end;
finally
sHTTPSource.Free;
end;
end;
I don't expect you to do all the work for me, but I'd really appreciate a hint in the right direction.
THTTPSend has a property .Cookies (TStringList) which takes name-value pairs (each one being a cookie). If you use the same THTTPSend instance to post through the login procedure then the cookies sent from YouTube will be captured and will be retained in future requests using the same THTTPSend instance. You can either do this each time (getting a new cookie) or you can hard (or soft) code the cookie information into the THTTPSend before making the request to the protected page.
You can also just do the login once and save the .cookies TStringList somewhere, each time assigning it to any new THTTPSend you create to make new requests.