docs: public Invocation getInvocation(final RpcRequest request, InterfaceDescriptor<?> descriptor) {
  		if (request == null) throw new NullPointerException("request");
  		if (descriptor == null) throw new NullPointerException("descriptor");
  
  		Invocation invocation = null;
  		LinkedList<String> parts = splitPath(request.getRelativePath());
  
  		while (!parts.isEmpty()) {
  			String part = parts.removeFirst();
  
  			// Find a method by a name.
  			MethodDescriptor<?, ?> method = descriptor.getMethod(part);
  			if (method == null) {
  				throw RpcException.badRequest("Method is not found: " + part);
  			}
  
  			// Check the required HTTP method.
  			if (method.isPost() && !request.isPost()) {
  				throw RpcException.methodNotAllowed("Method not allowed, POST required");
  			}
  
  			// Parse arguments.
  			List<Object> args = readArgs(method, parts, request.getQuery(), request.getPost());
  
  			// Create a root invocation,
  			// or a next invocation in a chain.
  			invocation = invocation != null ? invocation.next(method, args.toArray())
  			                                : Invocation.root(method, args.toArray());
  			if (method.isTerminal()) {
  				break;
  			}
  
  			// It's an interface method.
  			// Get the next interface and proceed parsing the parts.
  			descriptor = (InterfaceDescriptor<?>) method.getResult();
  		}
  
  		if (!parts.isEmpty()) {
  			// No more interface descriptors in a chain, but the parts are still present.
  			throw RpcException.badRequest("Failed to parse an invocation chain");
  		}
  
  		if (invocation == null) {
  			throw RpcException.badRequest("Invocation chain required");
  		}
  
  		if (!invocation.getMethod().isTerminal()) {
  			throw RpcException.badRequest("The last method must be a terminal one. "
  					+ "It must return a data type or be void.");
  		}
  
  		return invocation;
  	}