I think you should use then() - only criteria it doesn’t fit is your second one, but it’s easy to handle it yourself inside the closure you provide to it by matching on the Result you’re given.
If you return Ok from the closure, the chain continues with the value you put in there; if you return Err, the chain continues with the error instead.
and_then implies that new future is spawned, does not fit the case when result is ready. Although, It can be used with futures::result(...) to achieve the outcome.
Note that then and and_then both return something that’s an IntoFuture, so there’s no real difference from that standpoint. and_then requires that your Error type is the same as the upstream future (since it’s only called on success), whereas then does not.
The or_else there would essentially turn the chain into a Future<Item=Result<...>, Error=...>, which means the chain continues with a success value but the item itself is a Result. This means a subsequent map_err wouldn’t execute. I think then is more straightforward since you can change whether the chain continues with success or error in one combinator.