Then that lambda expression only has access the variables either created inside the lambda expression or explicitly captured. The “capture” part is the [] part, which is currently empty. So, no outside variables are captured. See
for a list of possible captures.
Note that this is especially tricky. The server.on() function just registers a callback function. This function may be called at any time later when there is a request. It would be fatal to register a function in setup() that captures a pointer or a buffer by reference that is not valid anymore once the setup() function is left. Once setup() exits, all its local variables get destroyed. So think very carefully if you want to take anything by copy ([=]) or reference ([&]).
For your function, I would do the following:
Get rid of our_ip_address completely. Just insert the expression WiFi.localIP().toString().c_str() as an argument to the format string when you need it
Allocate the ota_info_str buffer globally, that means outside of any function. Thus, it will be valid to be used anywhere and you don’t take of space on the stack of the function
use buffer-overflow safe functions for printing / string formatting. sprintf() doesn’t know how big the ota_info_str buffer is, so if the formatted string exceeds that length, it won’t know, and cause a buffer overflow. Use snprintf() instead that can take sizeof(ota_info_str) as the maximum length.